Commit 639f6dfd authored by seb's avatar seb
Browse files

- add status of acquisition in CtControl

- manage different Saving problem into CtSaving
- manage overun for Saving,Processing


git-svn-id: https://scm.blissgarden.org/svn/lima/trunk@198 45c4679d-1946-429d-baad-37912b19538b
parent 227f16f3
......@@ -26,6 +26,7 @@ namespace lima
DEB_CLASS_NAMESPC(DebModControl,"Control","Control");
friend class CtBufferFrameCB;
friend class CtSaving; // just to set saving error in stat
public:
enum ApplyPolicy {
......@@ -64,6 +65,26 @@ namespace lima
CtControl *m_cb_gen;
};
enum ErrorCode {NoError,
SaveUnknownError,SaveAccessError,SaveOverwriteError,SaveDiskFull,SaveOverun,
ProcessingOverun,
CameraError};
enum CameraErrorCode {NoCameraError}; /* @todo fix this */
struct Status
{
DEB_CLASS_NAMESPC(DebModControl,"Control::Status","Control");
public:
Status();
void reset();
AcqStatus AcquisitionStatus;
ErrorCode Error;
CameraErrorCode CameraStatus;
ImageStatus ImageCounters;
};
CtControl(HwInterface *hw);
~CtControl();
......@@ -79,7 +100,7 @@ namespace lima
void setApplyPolicy(ApplyPolicy policy);
void getApplyPolicy(ApplyPolicy &policy) const;
void getAcqStatus(AcqStatus& status) const; // from HW
void getStatus(Status& status) const; // from HW
void getImageStatus(ImageStatus& status) const;
void ReadImage(Data&,long frameNumber = -1);
......@@ -117,8 +138,8 @@ namespace lima
HwInterface *m_hw;
mutable Cond m_cond;
ImageStatus m_img_status;
mutable Status m_status;
CtSaving *m_ct_saving;
CtAcquisition *m_ct_acq;
CtImage *m_ct_image;
......@@ -138,6 +159,8 @@ namespace lima
bool m_autosave;
ImageStatusCallback *m_img_status_cb;
inline bool _checkOverun(Data&) const;
};
inline std::ostream& operator<<(std::ostream &os,
......@@ -152,6 +175,39 @@ namespace lima
<< ">";
return os;
}
inline std::ostream& operator<<(std::ostream &os,
const CtControl::Status &status)
{
os << "<";
switch(status.AcquisitionStatus)
{
case AcqReady:
os << "AcquisitionStatus=" << "Ready";break;
case AcqRunning:
os << "AcquisitionStatus=" << "Running";break;
default:
os << "AcquisitionStatus=" << "Failed";break;
}
if(status.AcquisitionStatus == AcqFault)
{
os << ", ";
switch(status.Error)
{
case(CtControl::SaveUnknownError): os << "Error=" << "Saving error";break;
case(CtControl::SaveAccessError): os << "Error=" << "Save access error";break;
case(CtControl::SaveOverwriteError): os << "Error=" << "Save overwrite error";break;
case(CtControl::SaveDiskFull): os << "Error=" << "Save disk full";break;
case(CtControl::SaveOverun): os << "Error=" << "Save overrun";break;
case(CtControl::ProcessingOverun): os << "Error=" << "Soft Processing overrun";break;
// should read CameraStatus instead @todo fix me
case(CtControl::CameraError): os << "Error=" << "Camera Error";break;
default: break;
}
}
os << status.ImageCounters;
return os;
}
} // namespace lima
#endif // CTCONTROL_H
......@@ -131,6 +131,7 @@ namespace lima {
class _SaveContainer;
class _SaveCBK;
friend class _SaveCBK;
friend class _SaveContainer;
CtControl &m_ctrl;
_SaveContainer *m_save_cnt;
......@@ -150,6 +151,7 @@ namespace lima {
void _takeHeader(std::map<long,HeaderMap>::iterator&, HeaderMap& header);
void _post_save_task(Data&,_SaveTask*);
void _save_finished(Data&);
void _setSavingError(CtControl::ErrorCode);
};
inline std::ostream& operator<<(std::ostream &os,const CtSaving::Parameters &params)
{
......
......@@ -31,6 +31,24 @@ using namespace lima;
virtual void imageStatusChanged(const CtControl::ImageStatus& status)=0;
};
enum ErrorCode {NoError,
SaveAccessError,SaveDiskFull,SaveOverun,
ProcessingOverun,
CameraError};
enum CameraErrorCode {NoCameraError}; /* @todo fix this */
struct Status
{
Status();
void reset();
AcqStatus AcquisitionStatus;
CtControl::ErrorCode Error;
CtControl::CameraErrorCode CameraStatus;
CtControl::ImageStatus ImageCounters;
};
CtControl(HwInterface *hw);
~CtControl();
......@@ -46,7 +64,7 @@ using namespace lima;
void setApplyPolicy(ApplyPolicy policy);
void getApplyPolicy(ApplyPolicy &policy /Out/) const;
void getAcqStatus(AcqStatus& status /Out/) const; // from HW
void getStatus(Status& status /Out/) const;
void getImageStatus(ImageStatus &imageStatus /Out/) const;
void ReadImage(Data&,long frameNumber = -1);
......
......@@ -138,7 +138,7 @@ void CtControl::getApplyPolicy(ApplyPolicy &policy) const
void CtControl::prepareAcq()
{
DEB_MEMBER_FUNCT();
m_img_status.reset();
m_status.reset();
DEB_TRACE() << "Apply Acquisition Parameters";
m_ct_acq->apply(m_policy);
......@@ -197,6 +197,7 @@ void CtControl::startAcq()
if (!m_ready)
throw LIMA_CTL_EXC(Error, "Run prepareAcq before starting acquisition");
m_ready = false;
m_hw->startAcq();
......@@ -212,15 +213,39 @@ void CtControl::stopAcq()
DEB_TRACE() << "Hardware Acquisition Stopped";
}
void CtControl::getAcqStatus(AcqStatus& status) const
void CtControl::getStatus(Status& status) const
{
DEB_MEMBER_FUNCT();
HwInterface::StatusType hw_status;
m_hw->getStatus(hw_status);
AutoMutex aLock(m_cond.mutex());
if(m_status.AcquisitionStatus != AcqFault)
{
const ImageStatus &anImageCnt = m_status.ImageCounters;
// Check if save has finnished
CtSaving::SavingMode aSavemode;
m_ct_saving->getSavingMode(aSavemode);
bool aSavingIdleFlag = true;
if(aSavemode != CtSaving::Manual)
aSavingIdleFlag = anImageCnt.LastImageAcquired == anImageCnt.LastImageSaved;
// End Check Save
// Check if processing has finnished
bool aProcessingIdle = anImageCnt.LastImageAcquired == anImageCnt.LastImageReady;
if(aSavingIdleFlag && aProcessingIdle)
{
HwInterface::Status aHwStatus;
m_hw->getStatus(aHwStatus);
m_status.AcquisitionStatus = aHwStatus.acq; // set the status to hw acquisition status
}
else
m_status.AcquisitionStatus = (aSavingIdleFlag || aProcessingIdle) ? AcqRunning : AcqReady;
}
status= hw_status.acq;
status= m_status;
DEB_RETURN() << DEB_VAR1(status);
}
......@@ -230,7 +255,7 @@ void CtControl::getImageStatus(ImageStatus& status) const
DEB_MEMBER_FUNCT();
AutoMutex aLock(m_cond.mutex());
status= m_img_status;
status= m_status.ImageCounters;
DEB_RETURN() << DEB_VAR1(status);
}
......@@ -251,9 +276,10 @@ void CtControl::ReadBaseImage(Data &aReturnData,long frameNumber)
DEB_PARAM() << DEB_VAR1(frameNumber);
AutoMutex aLock(m_cond.mutex());
ImageStatus &imgStatus = m_status.ImageCounters;
if(frameNumber < 0)
frameNumber = m_img_status.LastBaseImageReady;
else if(frameNumber > m_img_status.LastBaseImageReady)
frameNumber = imgStatus.LastBaseImageReady;
else if(frameNumber > imgStatus.LastBaseImageReady)
throw LIMA_CTL_EXC(Error, "Frame not available yet");
aLock.unlock();
m_ct_buffer->getFrame(aReturnData,frameNumber);
......@@ -274,7 +300,13 @@ void CtControl::newFrameReady(Data& fdata)
DEB_TRACE() << "Frame acq.nb " << fdata.frameNumber << " received";
AutoMutex aLock(m_cond.mutex());
m_img_status.LastImageAcquired= fdata.frameNumber;
if(_checkOverun(fdata))
{
aLock.unlock();
stopAcq(); // Stop Acquisition on overun
return;
}
m_status.ImageCounters.LastImageAcquired= fdata.frameNumber;
aLock.unlock();
TaskMgr *mgr = new TaskMgr();
......@@ -294,12 +326,13 @@ void CtControl::newFrameReady(Data& fdata)
{
newFrameToSave(fdata);
AutoMutex aLock(m_cond.mutex());
m_img_status.LastBaseImageReady = m_img_status.LastImageAcquired = fdata.frameNumber;
ImageStatus &imgStatus = m_status.ImageCounters;
imgStatus.LastBaseImageReady = imgStatus.LastImageAcquired = fdata.frameNumber;
}
if (m_img_status_cb)
m_img_status_cb->imageStatusChanged(m_img_status);
m_img_status_cb->imageStatusChanged(m_status.ImageCounters);
}
void CtControl::newBaseImageReady(Data &aData)
......@@ -308,7 +341,7 @@ void CtControl::newBaseImageReady(Data &aData)
DEB_PARAM() << DEB_VAR1(aData);
AutoMutex aLock(m_cond.mutex());
long expectedImageReady = m_img_status.LastBaseImageReady + 1;
long expectedImageReady = m_status.ImageCounters.LastBaseImageReady + 1;
bool img_status_changed = false;
if(aData.frameNumber == expectedImageReady)
{
......@@ -324,9 +357,10 @@ void CtControl::newBaseImageReady(Data &aData)
else
break;
}
m_img_status.LastBaseImageReady = expectedImageReady;
ImageStatus &imgStatus = m_status.ImageCounters;
imgStatus.LastBaseImageReady = expectedImageReady;
if(!m_op_ext_link_task_active)
m_img_status.LastImageReady = expectedImageReady;
imgStatus.LastImageReady = expectedImageReady;
img_status_changed = true;
}
......@@ -341,7 +375,7 @@ void CtControl::newBaseImageReady(Data &aData)
aLock.unlock();
if (img_status_changed && m_img_status_cb)
m_img_status_cb->imageStatusChanged(m_img_status);
m_img_status_cb->imageStatusChanged(m_status.ImageCounters);
}
......@@ -351,7 +385,7 @@ void CtControl::newImageReady(Data &aData)
DEB_PARAM() << DEB_VAR1(aData);
AutoMutex aLock(m_cond.mutex());
long expectedImageReady = m_img_status.LastImageReady + 1;
long expectedImageReady = m_status.ImageCounters.LastImageReady + 1;
bool img_status_changed = false;
if(aData.frameNumber == expectedImageReady)
{
......@@ -367,7 +401,7 @@ void CtControl::newImageReady(Data &aData)
else
break;
}
m_img_status.LastImageReady = expectedImageReady;
m_status.ImageCounters.LastImageReady = expectedImageReady;
img_status_changed = true;
}
......@@ -382,7 +416,7 @@ void CtControl::newImageReady(Data &aData)
aLock.unlock();
if (m_img_status_cb && img_status_changed)
m_img_status_cb->imageStatusChanged(m_img_status);
m_img_status_cb->imageStatusChanged(m_status.ImageCounters);
}
......@@ -400,11 +434,11 @@ void CtControl::newImageSaved(Data&)
{
DEB_MEMBER_FUNCT();
AutoMutex aLock(m_cond.mutex());
++m_img_status.LastImageSaved;
++m_status.ImageCounters.LastImageSaved;
aLock.unlock();
if (m_img_status_cb)
m_img_status_cb->imageStatusChanged(m_img_status);
m_img_status_cb->imageStatusChanged(m_status.ImageCounters);
}
void CtControl::newFrameToSave(Data& fdata)
......@@ -445,7 +479,46 @@ void CtControl::unregisterImageStatusCallback(ImageStatusCallback& cb)
cb.setImageStatusCallbackGen(NULL);
}
/** @brief this methode check if an overrun
* @warning this methode is call under lock
*/
bool CtControl::_checkOverun(Data &aData) const
{
DEB_MEMBER_FUNCT();
if(m_status.AcquisitionStatus == AcqFault) return true;
const ImageStatus &imageStatus = m_status.ImageCounters;
long imageToProcess = imageStatus.LastImageAcquired -
imageStatus.LastBaseImageReady;
long imageToSave = imageStatus.LastImageAcquired -
imageStatus.LastImageSaved;
long nb_buffers;
m_ct_buffer->getNumber(nb_buffers);
bool overrunFlag = false;
if(imageToProcess >= nb_buffers) // Process overrun
{
overrunFlag = true;
m_status.AcquisitionStatus = AcqFault;
m_status.Error = ProcessingOverun;
DEB_ERROR() << DEB_VAR1(m_status);
}
else if(imageToSave >= nb_buffers) // Save overrun
{
overrunFlag = true;
m_status.AcquisitionStatus = AcqFault;
m_status.Error = SaveOverun;
DEB_ERROR() << DEB_VAR1(m_status);
}
return overrunFlag;
}
// ----------------------------------------------------------------------------
// Struct ImageStatus
// ----------------------------------------------------------------------------
......@@ -467,7 +540,28 @@ void CtControl::ImageStatus::reset()
DEB_TRACE() << *this;
}
// ----------------------------------------------------------------------------
// Struct Status
// ----------------------------------------------------------------------------
CtControl::Status::Status() :
AcquisitionStatus(AcqReady),
Error(NoError),
CameraStatus(NoCameraError),
ImageCounters()
{
DEB_CONSTRUCTOR();
}
void CtControl::Status::reset()
{
DEB_MEMBER_FUNCT();
AcquisitionStatus = AcqReady;
Error = NoError;
CameraStatus = NoCameraError;
ImageCounters.reset();
}
// ----------------------------------------------------------------------------
// class ImageStatus
......
#include <sstream>
#include <unistd.h>
#ifdef __linux__
#include <sys/statvfs.h>
#endif
#include "CtSaving.h"
......@@ -444,7 +449,13 @@ void CtSaving::frameReady(Data &aData)
{
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(aData);
CtControl::Status status;
m_ctrl.getStatus(status);
if(status.AcquisitionStatus == AcqFault)
{
DEB_WARNING() << "Skip saving data: " << aData;
return;
}
AutoMutex aLock(m_cond.mutex());
switch(m_pars.savingMode)
{
......@@ -584,8 +595,26 @@ void CtSaving::_save_finished(Data &aData)
m_cond.signal();
}
}
/** @brief this methode set the error saving status in CtControl
*/
void CtSaving::_setSavingError(CtControl::ErrorCode anErrorCode)
{
DEB_MEMBER_FUNCT();
AutoMutex aLock(m_ctrl.m_cond.mutex());
if(m_ctrl.m_status.AcquisitionStatus != AcqFault)
{
m_ctrl.m_status.AcquisitionStatus = AcqFault;
m_ctrl.m_status.Error = anErrorCode;
DEB_ERROR() << DEB_VAR1(m_ctrl.m_status);
}
aLock.unlock();
m_ctrl.stopAcq();
}
/** @brief saving container
*
* This class manage file saving
......@@ -617,10 +646,45 @@ void CtSaving::_SaveContainer::_open()
std::string aFileName = pars.directory + DIR_SEPARATOR + pars.prefix + idx.str() + pars.suffix;
DEB_TRACE() << "Open file: " << aFileName;
m_fout.open(aFileName.c_str(),
std::ios_base::out | std::ios_base::binary);
if(pars.overwritePolicy == Abort &&
!access(aFileName.c_str(),R_OK))
{
m_saving._setSavingError(CtControl::SaveOverwriteError);
std::string output;
output = "Try to over write file: " + aFileName;
DEB_ERROR() << output;
throw LIMA_CTL_EXC(Error, output.c_str());
}
std::_Ios_Openmode openFlags = std::ios_base::out | std::ios_base::binary;
if(pars.overwritePolicy == Append)
openFlags |= std::ios_base::app;
else if(pars.overwritePolicy == Overwrite)
openFlags |= std::ios_base::trunc;
for(int nbTry = 0;nbTry < 5;++nbTry)
{
m_fout.exceptions(std::ios_base::goodbit);
m_fout.open(aFileName.c_str(),openFlags);
m_fout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
if(m_fout.fail())
{
std::string output;
if(access(pars.directory.c_str(),W_OK))
{
m_saving._setSavingError(CtControl::SaveAccessError);
output = "Can not write in directory: " + pars.directory;
DEB_ERROR() << output;
throw LIMA_CTL_EXC(Error,output.c_str());
}
}
else
{
DEB_TRACE() << "Open file: " << aFileName;
break;
}
}
}
}
......@@ -649,12 +713,51 @@ void CtSaving::_SaveContainer::writeFile(Data &aData,HeaderMap &aHeader)
m_saving.getParameters(pars);
_open();
try
{
if(pars.fileFormat == CtSaving::EDF)
_writeEdfHeader(aData,aHeader);
if(pars.fileFormat == CtSaving::EDF)
_writeEdfHeader(aData,aHeader);
m_fout.write((char*)aData.data(),aData.size());
m_fout.write((char*)aData.data(),aData.size());
}
catch(std::ios_base::failure &error)
{
DEB_ERROR() << "Write failed :" << error.what();
#ifdef __linux__
/** struct statvfs {
unsigned long f_bsize; // file system block size
unsigned long f_frsize; //fragment size
fsblkcnt_t f_blocks; // size of fs in f_frsize units
fsblkcnt_t f_bfree; // # free blocks
fsblkcnt_t f_bavail; // # free blocks for non-root
fsfilcnt_t f_files; // # inodes
fsfilcnt_t f_ffree; // # free inodes
fsfilcnt_t f_favail; // # free inodes for non-root
unsigned long f_fsid; // file system ID
unsigned long f_flag; //mount flags
unsigned long f_namemax; // maximum filename length
*/
//Check if disk full
struct statvfs vfs;
if(!statvfs(pars.directory.c_str(),&vfs))
{
if(vfs.f_favail < 1024 || vfs.f_bavail < 1024)
{
m_saving._setSavingError(CtControl::SaveDiskFull);
DEB_ERROR() << "Disk full!!!";
m_fout.close();
return;
}
};
#endif
m_saving._setSavingError(CtControl::SaveUnknownError);
m_fout.close();
return;
}
if(++m_written_frames == pars.framesPerFile)
_close();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment