Ignore:
Timestamp:
06/30/11 14:01:39 (13 years ago)
Author:
lyard
Message:
added 2 write error states + bug fix
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/datalogger.cc

    r11218 r11219  
    6363
    6464#include <fstream>
    65 #include <mutex>
    6665
    6766#include <boost/bind.hpp>
     
    199198        kSM_BadNightlyConfig = 0x101, ///< the folder specified for Nightly logging does not exist or has bad permissions
    200199        kSM_BadRunConfig = 0x102, ///<  the folder specified for the run logging does not exist or has wrong permissions or no run number
    201         kSM_WriteError = 0x103, ///< Denotes that an error occured while writing a file (text or fits).
     200        kSM_RunWriteError = 0x103, ///< Denotes that an error occured while writing a run file (text or fits).
     201        kSM_DailyWriteError = 0x103,///< Denots that an error occured while writing a daily file (text or fits).
    202202    } localstates_t;
    203203   
     
    297297    ///variables for computing statistics
    298298    DataLoggerStats fStatVar;
    299     ///mutex to make sure that the Stats are not accessed while updating
    300 //    mutex fStatsMutex;
    301     ///services notification thread
    302 //    boost::thread fMonitoringThread;
    303     ///end of the monitoring
    304 //    bool fContinueMonitoring;
    305299    ///stores the size of each file that is or was open
    306300    map<string, long> fFileSizesMap;
     
    353347    ///add a new run number
    354348    void AddNewRunNumber(int64_t newRun, Time time);
     349    std::vector<int64_t> previousRunNumbers;
    355350    ///removes the oldest run number, and close the relevant files.
    356351    void RemoveOldestRunNumber();
     
    380375    bool RememberFileOrigSizePlease(string& fileName, bool nightly);
    381376    ///Checks if the input osftream is in error state, and if so close it.
    382     bool CheckForOfstreamError(ofstream& out);
    383     ///Goes to Write error state and also closes all opened files
    384     void GoToWriteErrorState();
     377    bool CheckForOfstreamError(ofstream& out, bool isDailyStream);
     378    ///Goes to Write error states
     379    void GoToRunWriteErrorState();
     380    void GoToNightlyWriteErrorState();
    385381    ///Checks if a given path exist
    386382    bool DoesPathExist(string path);
     
    556552//! @param out the ofstream that should be checked
    557553//
    558 bool DataLogger::CheckForOfstreamError(ofstream& out)
     554bool DataLogger::CheckForOfstreamError(ofstream& out, bool isDailyStream)
    559555{
    560556    if (out.good())
     
    562558
    563559    Error("An error occured while writing to a text file. Closing it");
    564 //    if (out.is_open())
    565 //        out.close();
    566     GoToWriteErrorState();
     560    if (out.is_open())
     561        out.close();
     562    if (isDailyStream)
     563        GoToNightlyWriteErrorState();
     564    else
     565        GoToRunWriteErrorState();
    567566
    568567    return false;
    569 //    SetCurrentState(kSM_WriteError);
    570568}
    571569// --------------------------------------------------------------------------
     
    700698//
    701699//! Compiles a file name
     700//! @param run the run number
     701//! @param service the service name, if any
     702//! @param extension the extension to add, if any
     703//
     704string DataLogger::CompileFileName(const uint32_t run, const string& service, const string& extension)
     705{
     706       ostringstream str;
     707       //output base of file name
     708       str << setfill('0') << setw(8) << run;
     709
     710       //output service name
     711       if (!service.empty())
     712           str  << "_" << service;
     713
     714       //output appropriate extension
     715       if (!extension.empty())
     716           str << "." << extension;
     717       return str.str();
     718}
     719// --------------------------------------------------------------------------
     720//
     721//! Compiles a file name withh path
    702722//! @param path the base path where to put the file
    703723//! @param time the time at which the file is created
     
    706726//! @param extension the extension to add, if any
    707727//
    708 //string DataLogger::CompileFileName(const string &path, uint32_t run, const string &service, const string & extension, const Time &time)
    709 string DataLogger::CompileFileName(const uint32_t run, const string& service, const string& extension)//, const Time& time)
    710 {
    711        ostringstream str;
    712        //output base of file name
    713        str << setfill('0') << setw(8) << run;
    714 
    715        //output service name
    716        if (!service.empty())
    717            str  << "_" << service;
    718 
    719        //output appropriate extension
    720        if (!extension.empty())
    721            str << "." << extension;
    722        return str.str();
    723 }
    724 
    725728string DataLogger::CompileFileNameWithPath(const string& path, const uint32_t run, const string& service, const string& extension, const Time& time)
    726729{
     
    783786            {
    784787                y->second.runFile.Close();
    785 
    786                 Info("Closed: "+y->second.runFile.fFileName);
    787788            }
    788789    //if a grouping file is on, decrease the number of opened fits manually
     
    802803bool DataLogger::calculateTotalSizeWritten(DataLoggerStats& statVar, bool isPrinting)
    803804{
    804 //mutex
    805 //    if (!isPrinting)
    806 //        fStatsMutex.lock();
    807805#ifdef HAVE_FITS
    808806    if (isPrinting)
     
    872870    statVar.sizeWritten -= fBaseSizeRun;
    873871
    874 //mutex
    875 //    if (!isPrinting)
    876 //        fStatsMutex.unlock();
    877 
    878872    return shouldWarn;
    879873}
    880874
    881 // --------------------------------------------------------------------------
    882 //
    883 //! Monitor the number of opened files and total size written, and distributes this data through a Dim service
    884 //
    885 //
    886 /*
    887 void DataLogger::ServicesMonitoring()
    888 {
    889        struct statvfs vfs;
    890         if (!statvfs(fNightlyFilePath.c_str(), &vfs))
    891             fStatVar.freeSpace = vfs.f_bsize*vfs.f_bavail;
    892         else
    893             fStatVar.freeSpace = -1;
    894 
    895         DimDescribedService srvc ("DATA_LOGGER/STATS", "X:3", fStatVar, "Add description here");
    896         fPreviousSize = 0;
    897         //loop-wait for broadcast
    898         while (fContinueMonitoring)
    899         {
    900             if (fStatsPeriodDuration == 0.0f)
    901             {
    902                 sleep(0.1f);
    903                 continue;
    904             }
    905 
    906             sleep(fStatsPeriodDuration);
    907 
    908 
    909             fStatsMutex.lock();
    910 
    911             if (fStatVar.writingRate != 0) //if data has been written
    912             {
    913                 srvc.updateService();
    914 
    915                 if(fDebugIsOn)
    916                 {
    917                     ostringstream str;
    918                     str << "Size written: " << fStatVar.sizeWritten/1000 << " kB; writing rate: ";
    919                     str << fStatVar.writingRate/1000 << " kB/s; free space: ";
    920                     str << fStatVar.freeSpace/(1000*1000) << " MB";
    921                     Debug(str);
    922                 }
    923             }
    924             fStatsMutex.unlock();
    925         }
    926 }
    927 */
    928875// --------------------------------------------------------------------------
    929876//
     
    945892    AddStateName(kSM_BadNightlyConfig, "ErrNightlyFolder", "The folder for the nighly summary files is invalid.");
    946893    AddStateName(kSM_BadRunConfig,     "ErrRunFolder",     "The folder for the run files is invalid.");
    947     AddStateName(kSM_WriteError,       "ErrWrite",          "An error occured while writing to a file.");
     894    AddStateName(kSM_DailyWriteError,  "ErrDailyWrite",    "An error occured while writing to a daily (and run) file.");
     895    AddStateName(kSM_RunWriteError,    "ErrRunWrite",      "An error occured while writing to a run file.");
    948896
    949897    // Add the possible transitions for this machine
     
    952900        ("Start the nightly logging. Nightly file location must be specified already");
    953901
    954     AddEvent(kSM_Ready, "STOP", kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging, kSM_WriteError)
     902    AddEvent(kSM_Ready, "STOP", kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging, kSM_DailyWriteError, kSM_RunWriteError)
    955903        (boost::bind(&DataLogger::GoToReadyPlease, this))
    956904        ("Stop all data logging, close all files.");
     
    964912        ("Wait for a run to be started, open run-files as soon as a run number arrives.");
    965913
    966     AddEvent(kSM_Ready, "RESET", kSM_Error, kSM_BadNightlyConfig, kSM_BadRunConfig, kSM_WriteError)
     914    AddEvent(kSM_Ready, "RESET", kSM_Error, kSM_BadNightlyConfig, kSM_BadRunConfig, kSM_DailyWriteError, kSM_RunWriteError)
    967915        (boost::bind(&DataLogger::GoToReadyPlease, this))
    968916        ("Transition to exit error states. Closes the any open file.");
     
    1020968
    1021969     // provide services control commands
    1022      AddEvent("SET_DEUG_MODE", "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
     970     AddEvent("SET_DEBUG_MODE", "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
    1023971         (boost::bind(&DataLogger::SetDebugOnOff, this, _1))
    1024          ("Switch debug mode on or off. Debug mode prints ifnormation about every service written to a file."
     972         ("Switch debug mode on or off. Debug mode prints information about every service written to a file."
    1025973          "|Enable[bool]:Enable of disable debug mode (yes/no).");
    1026974
     
    10631011     fStatsMonitoring = new DimDescribedService(GetName() + "/STATS", "X:3", fStatVar, "Add description here");
    10641012
    1065 //mutex
    1066 //     fContinueMonitoring = true;
    1067 //     fMonitoringThread = boost::thread(boost::bind(&DataLogger::ServicesMonitoring, this));
    10681013     fBaseSizeNightly = 0;
    10691014     fBaseSizeRun = 0;
     
    10891034    //first let's go to the ready state
    10901035    GoToReadyPlease();
     1036    dim_lock();
    10911037    //release the services subscriptions
    10921038    fServiceSubscriptions.clear();
    1093     //exit the monitoring loop
    1094 //mutex
    1095 //    fContinueMonitoring = false;
    1096 //    fMonitoringThread.join();
     1039
    10971040    //clear any remaining run number (should remain only one)
    1098      while (fRunNumber.size() > 0)
     1041    while (fRunNumber.size() > 0)
    10991042     {
    11001043         RemoveOldestRunNumber();
    11011044     }
    1102 
     1045    dim_unlock();
    11031046    delete fOpenedNightlyFiles;
    11041047    delete fOpenedRunFiles;
     
    11691112    if (I==NULL)
    11701113        return;
     1114
     1115    //it may happen that we try to write a dimInfo while closing files. Prevent that with a dim_lock()
     1116    dim_lock();
     1117
    11711118    //check if the service pointer corresponds to something that we subscribed to
    11721119    //this is a fix for a bug that provides bad Infos when a server starts
     
    11741121    SubscriptionsListType::iterator x;
    11751122    map<string, SubscriptionType>::iterator y;
    1176      for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
     1123    for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
    11771124    {//find current service is subscriptions
    11781125        for (y=x->second.begin(); y!=x->second.end();y++)
     
    11881135    {
    11891136        DimServiceInfoList::infoHandler();
     1137        dim_unlock();
    11901138        return;
    11911139    }
    11921140    if (I->getSize() <= 0 || I->getData()==NULL)
     1141    {
     1142        dim_unlock();
    11931143        return;
    1194 
     1144    }
    11951145        // Make sure that getTimestampMillisecs is NEVER called before
    11961146        // getTimestamp is properly called
    11971147        // check that the message has been updated by something, i.e. must be different from its initial value
    11981148    if (I->getTimestamp() == 0)
     1149    {
     1150        dim_unlock();
    11991151        return;
    1200 
     1152    }
    12011153    // FIXME: Here we have to check if we have received the
    12021154    //        service with the run-number.
     
    12071159    ReportPlease(I, y->second);
    12081160
     1161    dim_unlock();
    12091162    //update the fits files sizes
    12101163    UpdateStatisticsService();
     
    12921245        return;
    12931246    }
     1247    for (std::vector<int64_t>::const_iterator it=previousRunNumbers.begin(); it != previousRunNumbers.end(); it++)
     1248    {
     1249        if (*it == newRun)
     1250        {
     1251            Error("Newly provided run number has already been used (or is still in use). Going to error state");
     1252            SetCurrentState(kSM_BadRunConfig);
     1253            return;
     1254        }
     1255    }
    12941256    if (fDebugIsOn)
    12951257    {
     
    13151277        {
    13161278            if (it->reportFile->is_open())
     1279            {
    13171280                it->reportFile->close();
     1281                Info("Closing: "+it->reportName);
     1282            }
    13181283#ifdef RUN_LOGS
    13191284            if (it->logFile->is_open())
     1285            {
    13201286                it->logFile->close();
     1287                Info("Closing: "+it->logName);
     1288            }
    13211289#endif
    13221290        }
     
    14961464        {
    14971465            fNightlyReportFile << header.str() << text << endl;
    1498             if (!CheckForOfstreamError(fNightlyReportFile))
     1466            if (!CheckForOfstreamError(fNightlyReportFile, true))
    14991467                return;
    15001468        }
     
    15031471        {
    15041472            *targetRunFile << header.str() << text << endl;
    1505             if (!CheckForOfstreamError(*targetRunFile))
     1473            if (!CheckForOfstreamError(*targetRunFile, false))
    15061474                return;
    15071475        }
     
    15151483        {
    15161484            MessageImp(fNightlyLogFile).Write(cTime, msg.str().c_str(), fQuality);
    1517             if (!CheckForOfstreamError(fNightlyLogFile))
     1485            if (!CheckForOfstreamError(fNightlyLogFile, true))
    15181486                return;
    15191487        }
     
    15211489        {
    15221490            MessageImp(*targetRunFile).Write(cTime, msg.str().c_str(), fQuality);
    1523             if (!CheckForOfstreamError(*targetRunFile))
     1491            if (!CheckForOfstreamError(*targetRunFile, false))
    15241492                return;
    15251493        }
     
    17881756}
    17891757
     1758// --------------------------------------------------------------------------
     1759//
     1760//!    Configure a given file name
     1761//! @param target
     1762//!        where to put the result
     1763//! @param type
     1764//!         what to append to the created path. currently only run or nightly
     1765//! @param evt
     1766//!         the event transporting the path
     1767//! @returns
     1768//!        currently only the current state.
     1769//
    17901770int DataLogger::ConfigureFileName(string &target, const string &type, const EventImp &evt)
    17911771{
     
    19061886    {
    19071887        fNightlyLogFile.close();
     1888        Info("Closed: "+fFullNightlyReportFileName);
    19081889        return kSM_BadNightlyConfig;
    19091890    }
     
    19801961        if (!sub.nightlyFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this, 0))
    19811962        {
    1982             GoToWriteErrorState();
     1963            GoToRunWriteErrorState();
    19831964            //SetCurrentState(kSM_WriteError);
    19841965            return;
     
    20262007                Error(str);
    20272008                cRunNumber->runFitsFile = shared_ptr<CCfits::FITS>();//NULL;
    2028                 GoToWriteErrorState();
     2009                GoToRunWriteErrorState();
    20292010                //SetCurrentState(kSM_WriteError);
    20302011                return;
     
    20422023            if (!sub.runFile.Open(partialName, serviceName, (cRunNumber->runFitsFile).get(), &fNumSubAndFitsData.numOpenFits, this, sub.runNumber))
    20432024            {
    2044                 GoToWriteErrorState();
     2025                GoToRunWriteErrorState();
    20452026                //SetCurrentState(kSM_WriteError);
    20462027                return;
     
    20492030        else
    20502031        {
    2051             if (sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this, sub.runNumber))
     2032            if (!sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this, sub.runNumber))
    20522033            {
    2053                 GoToWriteErrorState();
     2034                GoToRunWriteErrorState();
    20542035                //SetCurrentState(kSM_WriteError);
    20552036                return;
     
    20962077         switch (flist[i].first.first->name()[0])
    20972078         {
    2098          case 'c': dataQualifier << "B"; break; // FIXME: To be checked!
     2079         case 'c': dataQualifier << "S"; break;
    20992080         case 's': dataQualifier << "I"; break;
    21002081         case 'i': dataQualifier << "J"; break;
     
    21282109            if (!sub.nightlyFile.Write(sub.fConv.get()))
    21292110            {
    2130                 GoToWriteErrorState();
     2111                sub.nightlyFile.Close();
     2112                GoToNightlyWriteErrorState();
    21312113                return;
    21322114              //SetCurrentState(kSM_WriteError);
     
    21382120            if (!sub.runFile.Write(sub.fConv.get()))
    21392121            {
    2140                 GoToWriteErrorState();
     2122                sub.runFile.Close();
     2123                GoToRunWriteErrorState();
    21412124                return;
    21422125                //SetCurrentState(kSM_WriteError);
     
    21452128}
    21462129#endif //if has_fits
    2147 
    2148 void DataLogger::GoToWriteErrorState()
    2149 {
    2150     GoToReadyPlease();
    2151     SetCurrentState(kSM_WriteError);
    2152 }
    2153 
     2130// --------------------------------------------------------------------------
     2131//
     2132//! Go to Run Write Error State
     2133//      A write error has occurred. Checks what is the current state and take appropriate action
     2134void DataLogger::GoToRunWriteErrorState()
     2135{
     2136    if ((GetCurrentState() != kSM_RunWriteError) &&
     2137        (GetCurrentState() != kSM_DailyWriteError))
     2138        SetCurrentState(kSM_RunWriteError);
     2139}
     2140// --------------------------------------------------------------------------
     2141//
     2142//! Go to Nightly Write Error State
     2143//      A write error has occurred. Checks what is the current state and take appropriate action
     2144void DataLogger::GoToNightlyWriteErrorState()
     2145{
     2146    if (GetCurrentState() != kSM_DailyWriteError)
     2147        SetCurrentState(kSM_DailyWriteError);
     2148}
    21542149std::string DataLogger::SetCurrentState(int state, const char *txt, const std::string &cmd)
    21552150{
     
    23092304                str << "Writing FITS row " << i << " in " << groupName << ": " << text << " (file_write_tblbytes, rc=" << status << ")";
    23102305                Error(str);
    2311                 GoToWriteErrorState();
     2306                GoToRunWriteErrorState();
     2307                delete groupFile;
    23122308                return;
    23132309            }
     
    23322328        Debug("Stopping Run Logging...");   
    23332329    }
     2330    //it may be that dim tries to write a dimInfo at the same time as we're closing files. Prevent this
     2331
     2332    dim_lock();
    23342333    for (list<RunNumberType>::const_iterator it=fRunNumber.begin(); it != fRunNumber.end(); it++)
    23352334    {
     
    23422341#ifdef RUN_LOGS
    23432342        it->logFile->close();
     2343        Info("Closed: "+it->logName);
     2344
    23442345#endif
    23452346        it->reportFile->close();
     2347        Info("Closed: "+it->reportName);
    23462348    }
    23472349
     
    23622364        RemoveOldestRunNumber();
    23632365    }
    2364 
     2366    dim_unlock();
    23652367    return kSM_WaitingRun;
    23662368}
     
    23792381   if (GetCurrentState() == kSM_Logging)
    23802382       StopRunPlease();
    2381 
     2383   //it may be that dim tries to write a dimInfo while we're closing files. Prevent that
     2384   dim_lock();
     2385   const string baseFileName = CompileFileNameWithPath(fNightlyFilePath, "", "");
    23822386    if (fNightlyLogFile.is_open())
     2387    {
    23832388        fNightlyLogFile.close();
     2389        Info("Closed: "+baseFileName+".log");
     2390    }
    23842391    if (fNightlyReportFile.is_open())
     2392    {
    23852393        fNightlyReportFile.close();
    2386        
     2394        Info("Closed: "+baseFileName+".rep");
     2395    }
    23872396#ifdef HAVE_FITS
    23882397    for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++)
     
    23902399        {
    23912400            if (j->second.nightlyFile.IsOpen())
    2392                 j->second.nightlyFile.Close();;
     2401                j->second.nightlyFile.Close();
    23932402        }
    23942403#endif
     
    24042413    CreateFitsGrouping(fOpenedNightlyFits, 0);
    24052414#endif
     2415    dim_unlock();
    24062416    return kSM_Ready;
    24072417}
Note: See TracChangeset for help on using the changeset viewer.