diff --git a/slsReceiverSoftware/src/BinaryMasterFile.cpp b/slsReceiverSoftware/src/BinaryMasterFile.cpp index 2ca87bd7c..f6d0942fc 100644 --- a/slsReceiverSoftware/src/BinaryMasterFile.cpp +++ b/slsReceiverSoftware/src/BinaryMasterFile.cpp @@ -3,12 +3,12 @@ #include "BinaryMasterFile.h" #include "MasterAttributes.h" -void BinaryMasterFile::CreateMasterFile(const std::string filePath, - const std::string fileNamePrefix, - const uint64_t fileIndex, - const bool overWriteEnable, - const bool silentMode, - MasterAttributes *attr) { +std::string BinaryMasterFile::CreateMasterFile(const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, + const bool overWriteEnable, + const bool silentMode, + MasterAttributes *attr) { // create file name std::ostringstream os; os << filePath << "/" << fileNamePrefix << "_master" @@ -28,11 +28,31 @@ void BinaryMasterFile::CreateMasterFile(const std::string filePath, throw sls::RuntimeError( "Could not create/overwrite binary master file " + fileName); } - if (!silentMode) { - LOG(logINFO) << "Master File: " << fileName; + + std::string message = BinaryMasterFile::GetMasterAttributes(attr); + if (fwrite((void *)message.c_str(), 1, message.length(), fd) != + message.length()) { + throw sls::RuntimeError( + "Master binary file incorrect number of bytes written to file"); } - attr->WriteMasterBinaryAttributes(fd); if (fd) { fclose(fd); } + if (!silentMode) { + LOG(logINFO) << "Master File: " << fileName; + } + return fileName; +} + +std::string BinaryMasterFile::GetMasterAttributes(MasterAttributes *attr) { + rapidjson::StringBuffer s; + rapidjson::Writer writer(s); + writer.StartObject(); + + attr->GetCommonBinaryAttributes(&writer); + attr->GetSpecificBinaryAttributes(&writer); + attr->GetFinalBinaryAttributes(&writer); + + writer.EndObject(); + return s.GetString(); } diff --git a/slsReceiverSoftware/src/BinaryMasterFile.h b/slsReceiverSoftware/src/BinaryMasterFile.h index 2ffe3e1d2..aaac736ab 100644 --- a/slsReceiverSoftware/src/BinaryMasterFile.h +++ b/slsReceiverSoftware/src/BinaryMasterFile.h @@ -8,9 +8,13 @@ class BinaryMasterFile : private virtual slsDetectorDefs { public: - static void CreateMasterFile(const std::string filePath, - const std::string fileNamePrefix, - const uint64_t fileIndex, - const bool overWriteEnable, - const bool silentMode, MasterAttributes *attr); + static std::string CreateMasterFile(const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, + const bool overWriteEnable, + const bool silentMode, + MasterAttributes *attr); + + private: + static std::string GetMasterAttributes(MasterAttributes *attr); }; \ No newline at end of file diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index dc1bc2d2d..78985eaef 100644 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -94,10 +94,6 @@ void DataProcessor::DeleteFiles() { delete dataFile_; dataFile_ = nullptr; } - /* if (masterFile_) { - delete masterFile_; - masterFile_ = nullptr; - }*/ #ifdef HDF5C if (virtualFile_) { delete virtualFile_; @@ -107,13 +103,13 @@ void DataProcessor::DeleteFiles() { } void DataProcessor::SetupFileWriter(const bool filewriteEnable, const fileFormat fileFormatType, - std::mutex *hdf5Lib) { + std::mutex *hdf5LibMutex) { DeleteFiles(); if (filewriteEnable) { switch (fileFormatType) { #ifdef HDF5C case HDF5: - dataFile_ = new HDF5DataFile(index, hdf5Lib); + dataFile_ = new HDF5DataFile(index, hdf5LibMutex); break; #endif case BINARY: @@ -178,7 +174,7 @@ void DataProcessor::CreateVirtualFile( const int modulePos, const int numUnitsPerReadout, const uint32_t maxFramesPerFile, const uint64_t numImages, const uint32_t dynamicRange, const int numModX, const int numModY, - std::mutex *hdf5Lib) { + std::mutex *hdf5LibMutex) { if (virtualFile_) { delete virtualFile_; @@ -186,7 +182,7 @@ void DataProcessor::CreateVirtualFile( bool gotthard25um = ((detectorType_ == GOTTHARD || detectorType_ == GOTTHARD2) && (numModX * numModY) == 2); - virtualFile_ = new HDF5VirtualFile(hdf5Lib, gotthard25um); + virtualFile_ = new HDF5VirtualFile(hdf5LibMutex, gotthard25um); // maxframesperfile = 0 for infinite files uint32_t framesPerFile = @@ -204,7 +200,9 @@ void DataProcessor::CreateVirtualFile( dataFile_->GetParameterNames(), dataFile_->GetParameterDataTypes()); } -void DataProcessor::LinkDataInMasterFile(const bool silentMode) { +void DataProcessor::LinkDataInMasterFile(const string &masterFileName, + const bool silentMode, + std::mutex *hdf5LibMutex) { std::string fname, datasetName; if (virtualFile_) { auto res = virtualFile_->GetFileAndDatasetName(); @@ -216,15 +214,17 @@ void DataProcessor::LinkDataInMasterFile(const bool silentMode) { datasetName = res[1]; } // link in master - masterFile_->LinkDataFile(fname, datasetName, - dataFile_->GetParameterNames(), silentMode); + HDF5MasterFile::LinkDataFile(masterFileName, fname, datasetName, + dataFile_->GetParameterNames(), silentMode, + &hdf5LibMutex); } #endif -void DataProcessor::CreateMasterFile( - const std::string filePath, const std::string fileNamePrefix, +std::string DataProcessor::CreateMasterFile( + const std::string &filePath, const std::string &fileNamePrefix, const uint64_t fileIndex, const bool overWriteEnable, bool silentMode, - const fileFormat fileFormatType, MasterAttributes *attr) { + const fileFormat fileFormatType, MasterAttributes *attr, + std::mutex *hdf5LibMutex) { attr->framesInFile = numFramesCaught_; @@ -232,13 +232,14 @@ void DataProcessor::CreateMasterFile( switch (fileFormatType) { #ifdef HDF5C case HDF5: - masterFile = sls::make_unique(hdf5Lib); - break; + return HDF5MasterFile::CreateMasterFile(filePath, fileNamePrefix, + fileIndex, overWriteEnable, + silentMode, attr, hdf5LibMutex); #endif case BINARY: - BinaryMasterFile::CreateMasterFile(filePath, fileNamePrefix, fileIndex, - overWriteEnable, silentMode, attr); - break; + return BinaryMasterFile::CreateMasterFile(filePath, fileNamePrefix, + fileIndex, overWriteEnable, + silentMode, attr); default: throw sls::RuntimeError("Unknown file format (compile with hdf5 flags"); } diff --git a/slsReceiverSoftware/src/DataProcessor.h b/slsReceiverSoftware/src/DataProcessor.h index 0bbeb3f40..2b8aacb9f 100644 --- a/slsReceiverSoftware/src/DataProcessor.h +++ b/slsReceiverSoftware/src/DataProcessor.h @@ -45,7 +45,8 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { void CloseFiles(); void DeleteFiles(); void SetupFileWriter(const bool filewriteEnable, - const fileFormat fileFormatType, std::mutex *hdf5Lib); + const fileFormat fileFormatType, + std::mutex *hdf5LibMutex); void CreateFirstFiles(const std::string filePath, const std::string fileNamePrefix, @@ -58,22 +59,26 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { const bool detectorDataStream); #ifdef HDF5C uint32_t GetFilesInAcquisition() const; - void CreateVirtualFile(const std::string filePath, - const std::string fileNamePrefix, + void CreateVirtualFile(const std::string &filePath, + const std::string &fileNamePrefix, const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, const int modulePos, const int numUnitsPerReadout, const uint32_t maxFramesPerFile, const uint64_t numImages, const uint32_t dynamicRange, const int numModX, - const int numModY, std::mutex *hdf5Lib); - void LinkDataInMasterFile(const bool silentMode); + const int numModY, std::mutex *hdf5LibMutex); + void LinkDataInMasterFile(const string &masterFileName, + const bool silentMode, std::mutex *hdf5LibMutex); #endif - void CreateMasterFile(const std::string filePath, - const std::string fileNamePrefix, - const uint64_t fileIndex, const bool overWriteEnable, - bool silentMode, const fileFormat fileFormatType, - MasterAttributes *attr); + + std::string CreateMasterFile(const std::string &filePath, + const std::string &fileNamePrefix, + const uint64_t fileIndex, + const bool overWriteEnable, bool silentMode, + const fileFormat fileFormatType, + MasterAttributes *attr, + std::mutex *hdf5LibMutex); /** * Call back for raw data * args to raw data ready callback are diff --git a/slsReceiverSoftware/src/HDF5MasterFile.cpp b/slsReceiverSoftware/src/HDF5MasterFile.cpp index 2c3721501..ea425f14d 100644 --- a/slsReceiverSoftware/src/HDF5MasterFile.cpp +++ b/slsReceiverSoftware/src/HDF5MasterFile.cpp @@ -3,30 +3,12 @@ #include "HDF5MasterFile.h" #include "MasterAttributes.h" -HDF5MasterFile::HDF5MasterFile(std::mutex *hdf5Lib) - : File(HDF5), hdf5Lib_(hdf5Lib) {} - -HDF5MasterFile::~HDF5MasterFile() { CloseFile(); } - -void HDF5MasterFile::CloseFile() { - std::lock_guard lock(*hdf5Lib_); - try { - Exception::dontPrint(); // to handle errors - if (fd_) { - fd_->close(); - delete fd_; - fd_ = nullptr; - } - } catch (const Exception &error) { - LOG(logERROR) << "Could not close master HDF5 handles"; - error.printErrorStack(); - } -} - -void HDF5MasterFile::LinkDataFile(std::string dataFilename, - std::string dataSetname, +void HDF5MasterFile::LinkDataFile(const std::string &masterFileName, + const std::string &dataFilename, + const std::string &dataSetname, const std::vector parameterNames, - const bool silentMode) { + const bool silentMode, + std::mutex *hdf5LibMutex) { std::lock_guard lock(*hdf5Lib_); try { @@ -36,7 +18,7 @@ void HDF5MasterFile::LinkDataFile(std::string dataFilename, flist.setFcloseDegree(H5F_CLOSE_STRONG); // open master file - H5File masterfd(fileName_.c_str(), H5F_ACC_RDWR, + H5File masterfd(masterFileName.c_str(), H5F_ACC_RDWR, FileCreatPropList::DEFAULT, flist); // open data file @@ -69,7 +51,7 @@ void HDF5MasterFile::LinkDataFile(std::string dataFilename, masterfd.close(); } catch (const Exception &error) { error.printErrorStack(); - CloseFile(); + fd.close(); throw sls::RuntimeError("Could not link in master hdf5 file"); } if (!silentMode) { @@ -77,17 +59,15 @@ void HDF5MasterFile::LinkDataFile(std::string dataFilename, } } -void HDF5MasterFile::CreateMasterFile(const std::string filePath, - const std::string fileNamePrefix, - const uint64_t fileIndex, - const bool overWriteEnable, - const bool silentMode, - MasterAttributes *attr) { +std::string HDF5MasterFile::CreateMasterFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, + MasterAttributes *attr, std::mutex *hdf5LibMutex) { std::ostringstream os; os << filePath << "/" << fileNamePrefix << "_master" << "_" << fileIndex << ".h5"; - fileName_ = os.str(); + std::string fileName = os.str(); std::lock_guard lock(*hdf5Lib_); @@ -96,67 +76,39 @@ void HDF5MasterFile::CreateMasterFile(const std::string filePath, FileAccPropList flist; flist.setFcloseDegree(H5F_CLOSE_STRONG); - fd_ = nullptr; - if (!(overWriteEnable)) - fd_ = new H5File(fileName_.c_str(), H5F_ACC_EXCL, - FileCreatPropList::DEFAULT, flist); - else - fd_ = new H5File(fileName_.c_str(), H5F_ACC_TRUNC, - FileCreatPropList::DEFAULT, flist); + + unsigned int createFlags = H5F_ACC_EXCL; + if (overWriteEnable) { + createFlags = H5F_ACC_TRUNC; + } + H5File fd(fileName.c_str(), createFlags, FileCreatPropList::DEFAULT, + flist); // attributes - version double dValue = HDF5_WRITER_VERSION; DataSpace dataspace_attr = DataSpace(H5S_SCALAR); - Attribute attribute = fd_->createAttribute( + Attribute attribute = fd.createAttribute( "version", PredType::NATIVE_DOUBLE, dataspace_attr); attribute.write(PredType::NATIVE_DOUBLE, &dValue); // Create a group in the file - Group group1(fd_->createGroup("entry")); + Group group1(fd.createGroup("entry")); Group group2(group1.createGroup("data")); Group group3(group1.createGroup("instrument")); Group group4(group3.createGroup("beam")); Group group5(group3.createGroup("detector")); Group group6(group1.createGroup("sample")); - // TODO find a way to get complete group link - attrGroupName_ = "/entry/instrument/detector"; - - attr->WriteMasterHDF5Attributes(fd_, &group5); - fd_->close(); - + attr->WriteMasterHDF5Attributes(&fd, &group5); + fd.close(); } catch (const Exception &error) { error.printErrorStack(); - CloseFile(); + fd.close(); throw sls::RuntimeError( "Could not create/overwrite master HDF5 handles"); } if (!silentMode) { - LOG(logINFO) << "Master File: " << fileName_; + LOG(logINFO) << "Master File: " << fileName; } + return fileName; } - -void HDF5MasterFile::UpdateMasterFile(MasterAttributes *attr, bool silentMode) { - std::lock_guard lock(*hdf5Lib_); - - try { - Exception::dontPrint(); // to handle errors - FileAccPropList flist; - flist.setFcloseDegree(H5F_CLOSE_STRONG); - fd_ = new H5File(fileName_.c_str(), H5F_ACC_RDWR, - FileCreatPropList::DEFAULT, flist); - - Group group = fd_->openGroup(attrGroupName_.c_str()); - attr->WriteFinalHDF5Attributes(fd_, &group); - fd_->close(); - - } catch (const Exception &error) { - error.printErrorStack(); - CloseFile(); - throw sls::RuntimeError( - "Could not create/overwrite master HDF5 handles"); - } - if (!silentMode) { - LOG(logINFO) << "Updated Master File"; - } -} \ No newline at end of file diff --git a/slsReceiverSoftware/src/HDF5MasterFile.h b/slsReceiverSoftware/src/HDF5MasterFile.h index 350a2da90..bb5431ab7 100644 --- a/slsReceiverSoftware/src/HDF5MasterFile.h +++ b/slsReceiverSoftware/src/HDF5MasterFile.h @@ -7,23 +7,16 @@ #include class HDF5MasterFile : private virtual slsDetectorDefs, public File { - public: - HDF5MasterFile(std::mutex *hdf5Lib); - ~HDF5MasterFile(); - - void LinkDataFile(std::string dataFilename, std::string dataSetname, + void LinkDataFile(const std::string &masterFileName, + const std::string &dataFilename, + const &std::string dataSetname, const std::vector parameterNames, - const bool silentMode) override; - void CreateMasterFile(const std::string filePath, - const std::string fileNamePrefix, - const uint64_t fileIndex, const bool overWriteEnable, - const bool silentMode, - MasterAttributes *attr) override; - - private: - std::mutex *hdf5Lib_; - H5File *fd_{nullptr}; - std::string fileName_; - std::string attrGroupName_; + const bool silentMode, std::mutex *hdf5LibMutex); + std::string CreateMasterFile(const std::string &filePath, + const std::string &fileNamePrefix, + const uint64_t fileIndex, + const bool overWriteEnable, + const bool silentMode, MasterAttributes *attr, + std::mutex *hdf5LibMutex); }; \ No newline at end of file diff --git a/slsReceiverSoftware/src/HDF5VirtualFile.cpp b/slsReceiverSoftware/src/HDF5VirtualFile.cpp index 015ad0ae3..fe1f0d4e3 100644 --- a/slsReceiverSoftware/src/HDF5VirtualFile.cpp +++ b/slsReceiverSoftware/src/HDF5VirtualFile.cpp @@ -5,8 +5,8 @@ #include -HDF5VirtualFile::HDF5VirtualFile(std::mutex *hdf5Lib, bool g25) - : File(HDF5), hdf5Lib_(hdf5Lib), gotthard25um(g25) {} +HDF5VirtualFile::HDF5VirtualFile(std::mutex *hdf5LibMutex, bool g25) + : File(HDF5), hdf5Lib_(hdf5LibMutex), gotthard25um(g25) {} HDF5VirtualFile::~HDF5VirtualFile() { CloseFile(); } @@ -30,7 +30,7 @@ void HDF5VirtualFile::CloseFile() { } void HDF5VirtualFile::CreateVirtualFile( - const std::string filePath, const std::string fileNamePrefix, + const &std::string filePath, const &std::string fileNamePrefix, const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, const int modulePos, const int numUnitsPerReadout, const uint32_t maxFramesPerFile, const uint64_t numImages, diff --git a/slsReceiverSoftware/src/HDF5VirtualFile.h b/slsReceiverSoftware/src/HDF5VirtualFile.h index 89b1c0b60..eee01dad5 100644 --- a/slsReceiverSoftware/src/HDF5VirtualFile.h +++ b/slsReceiverSoftware/src/HDF5VirtualFile.h @@ -9,13 +9,13 @@ class HDF5VirtualFile : private virtual slsDetectorDefs, public File { public: - HDF5VirtualFile(std::mutex *hdf5Lib, bool g25); + HDF5VirtualFile(std::mutex *hdf5LibMutex, bool g25); ~HDF5VirtualFile(); std::array GetFileAndDatasetName() const override; void CloseFile() override; void CreateVirtualFile( - const std::string filePath, const std::string fileNamePrefix, + const std::string &filePath, const std::string &fileNamePrefix, const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, const int modulePos, const int numUnitsPerReadout, const uint32_t maxFramesPerFile, diff --git a/slsReceiverSoftware/src/Implementation.cpp b/slsReceiverSoftware/src/Implementation.cpp index 64cff45ae..4d979f7da 100644 --- a/slsReceiverSoftware/src/Implementation.cpp +++ b/slsReceiverSoftware/src/Implementation.cpp @@ -369,7 +369,7 @@ void Implementation::setFileFormat(const fileFormat f) { throw sls::RuntimeError("Unknown file format"); } for (const auto &it : dataProcessor) - it->SetupFileWriter(fileWriteEnable, fileFormatType, &hdf5Lib); + it->SetupFileWriter(fileWriteEnable, fileFormatType, &hdf5LibMutex); } LOG(logINFO) << "File Format: " << sls::ToString(fileFormatType); @@ -405,7 +405,7 @@ void Implementation::setFileWriteEnable(const bool b) { if (fileWriteEnable != b) { fileWriteEnable = b; for (const auto &it : dataProcessor) - it->SetupFileWriter(fileWriteEnable, fileFormatType, &hdf5Lib); + it->SetupFileWriter(fileWriteEnable, fileFormatType, &hdf5LibMutex); } LOG(logINFO) << "File Write Enable: " << (fileWriteEnable ? "enabled" : "disabled"); @@ -741,116 +741,121 @@ void Implementation::SetupWriter() { } void Implementation::StartMasterWriter() { - // master file - if (masterFileWriteEnable) { - std::unique_ptr masterAttributes; - switch (detType) { - case GOTTHARD: - masterAttributes = sls::make_unique(); - break; - case JUNGFRAU: - masterAttributes = sls::make_unique(); - break; - case EIGER: - masterAttributes = sls::make_unique(); - break; - case MYTHEN3: - masterAttributes = sls::make_unique(); - break; - case GOTTHARD2: - masterAttributes = sls::make_unique(); - break; - case MOENCH: - masterAttributes = sls::make_unique(); - break; - case CHIPTESTBOARD: - masterAttributes = sls::make_unique(); - break; - default: - throw sls::RuntimeError( - "Unknown detector type to set up master file attributes"); - } - masterAttributes->detType = detType; - masterAttributes->timingMode = timingMode; - xy nm{numModules.x, numModules.y}; - if (quadEnable) { - nm.x = 1; - nm.y = 2; - } - masterAttributes->geometry = xy(nm.x, nm.y); - masterAttributes->imageSize = generalData->imageSize; - masterAttributes->nPixels = - xy(generalData->nPixelsX, generalData->nPixelsY); - masterAttributes->maxFramesPerFile = framesPerFile; - masterAttributes->frameDiscardMode = frameDiscardMode; - masterAttributes->framePadding = framePadding; - masterAttributes->scanParams = scanParams; - masterAttributes->totalFrames = numberOfTotalFrames; - masterAttributes->exptime = acquisitionTime; - masterAttributes->period = acquisitionPeriod; - masterAttributes->burstMode = burstMode; - masterAttributes->numUDPInterfaces = numUDPInterfaces; - masterAttributes->dynamicRange = dynamicRange; - masterAttributes->tenGiga = tengigaEnable; - masterAttributes->thresholdEnergyeV = thresholdEnergyeV; - masterAttributes->thresholdAllEnergyeV = thresholdAllEnergyeV; - masterAttributes->subExptime = subExpTime; - masterAttributes->subPeriod = subPeriod; - masterAttributes->quad = quadEnable; - masterAttributes->readNRows = readNRows; - masterAttributes->ratecorr = rateCorrections; - masterAttributes->adcmask = - tengigaEnable ? adcEnableMaskTenGiga : adcEnableMaskOneGiga; - masterAttributes->analog = - (readoutType == ANALOG_ONLY || readoutType == ANALOG_AND_DIGITAL) - ? 1 - : 0; - masterAttributes->analogSamples = numberOfAnalogSamples; - masterAttributes->digital = - (readoutType == DIGITAL_ONLY || readoutType == ANALOG_AND_DIGITAL) - ? 1 - : 0; - masterAttributes->digitalSamples = numberOfDigitalSamples; - masterAttributes->dbitoffset = ctbDbitOffset; - masterAttributes->dbitlist = 0; - for (auto &i : ctbDbitList) { - masterAttributes->dbitlist |= (1 << i); - } - masterAttributes->roi = roi; - masterAttributes->counterMask = counterMask; - masterAttributes->exptime1 = acquisitionTime1; - masterAttributes->exptime2 = acquisitionTime2; - masterAttributes->exptime3 = acquisitionTime3; - masterAttributes->gateDelay1 = gateDelay1; - masterAttributes->gateDelay2 = gateDelay2; - masterAttributes->gateDelay3 = gateDelay3; - masterAttributes->gates = numberOfGates; - masterAttributes->additionalJsonHeader = additionalJsonHeader; - - try { - dataProcessor[0]->CreateMasterFile( - filePath, fileName, fileIndex, overwriteEnable, silentMode, - fileFormatType, masterAttributes.get()); - } catch (...) { - ; // ignore it and just print it - } - } -#ifdef HDF5C - if (fileFormatType == HDF5) { - // virtual hdf5 file (if multiple files) - if (dataProcessor[0]->GetFilesInAcquisition() > 1 || - (numModules.x * numModules.y) > 1) { - dataProcessor[0]->CreateVirtualFile( - filePath, fileName, fileIndex, overwriteEnable, silentMode, - modulePos, numUDPInterfaces, framesPerFile, numberOfTotalFrames, - dynamicRange, numModules.x, numModules.y, &hdf5Lib); - } - // link file in master + try { + std::string masterFileName; + // master file if (masterFileWriteEnable) { - dataProcessor[0]->LinkDataInMasterFile(silentMode); + std::unique_ptr masterAttributes{nullptr}; + switch (detType) { + case GOTTHARD: + masterAttributes = sls::make_unique(); + break; + case JUNGFRAU: + masterAttributes = sls::make_unique(); + break; + case EIGER: + masterAttributes = sls::make_unique(); + break; + case MYTHEN3: + masterAttributes = sls::make_unique(); + break; + case GOTTHARD2: + masterAttributes = + sls::make_unique(); + break; + case MOENCH: + masterAttributes = sls::make_unique(); + break; + case CHIPTESTBOARD: + masterAttributes = sls::make_unique(); + break; + default: + throw sls::RuntimeError( + "Unknown detector type to set up master file attributes"); + } + masterAttributes->detType = detType; + masterAttributes->timingMode = timingMode; + xy nm{numModules.x, numModules.y}; + if (quadEnable) { + nm.x = 1; + nm.y = 2; + } + masterAttributes->geometry = xy(nm.x, nm.y); + masterAttributes->imageSize = generalData->imageSize; + masterAttributes->nPixels = + xy(generalData->nPixelsX, generalData->nPixelsY); + masterAttributes->maxFramesPerFile = framesPerFile; + masterAttributes->frameDiscardMode = frameDiscardMode; + masterAttributes->framePadding = framePadding; + masterAttributes->scanParams = scanParams; + masterAttributes->totalFrames = numberOfTotalFrames; + masterAttributes->exptime = acquisitionTime; + masterAttributes->period = acquisitionPeriod; + masterAttributes->burstMode = burstMode; + masterAttributes->numUDPInterfaces = numUDPInterfaces; + masterAttributes->dynamicRange = dynamicRange; + masterAttributes->tenGiga = tengigaEnable; + masterAttributes->thresholdEnergyeV = thresholdEnergyeV; + masterAttributes->thresholdAllEnergyeV = thresholdAllEnergyeV; + masterAttributes->subExptime = subExpTime; + masterAttributes->subPeriod = subPeriod; + masterAttributes->quad = quadEnable; + masterAttributes->readNRows = readNRows; + masterAttributes->ratecorr = rateCorrections; + masterAttributes->adcmask = + tengigaEnable ? adcEnableMaskTenGiga : adcEnableMaskOneGiga; + masterAttributes->analog = (readoutType == ANALOG_ONLY || + readoutType == ANALOG_AND_DIGITAL) + ? 1 + : 0; + masterAttributes->analogSamples = numberOfAnalogSamples; + masterAttributes->digital = (readoutType == DIGITAL_ONLY || + readoutType == ANALOG_AND_DIGITAL) + ? 1 + : 0; + masterAttributes->digitalSamples = numberOfDigitalSamples; + masterAttributes->dbitoffset = ctbDbitOffset; + masterAttributes->dbitlist = 0; + for (auto &i : ctbDbitList) { + masterAttributes->dbitlist |= (1 << i); + } + masterAttributes->roi = roi; + masterAttributes->counterMask = counterMask; + masterAttributes->exptime1 = acquisitionTime1; + masterAttributes->exptime2 = acquisitionTime2; + masterAttributes->exptime3 = acquisitionTime3; + masterAttributes->gateDelay1 = gateDelay1; + masterAttributes->gateDelay2 = gateDelay2; + masterAttributes->gateDelay3 = gateDelay3; + masterAttributes->gates = numberOfGates; + masterAttributes->additionalJsonHeader = additionalJsonHeader; + + // create master file + masterFileName = dataProcessor[0]->CreateMasterFile( + filePath, fileName, fileIndex, overwriteEnable, silentMode, + fileFormatType, masterAttributes.get(), &hdf5LibMutex); + } +#ifdef HDF5C + if (fileFormatType == HDF5) { + // create virtual hdf5 file (if multiple files) + if (dataProcessor[0]->GetFilesInAcquisition() > 1 || + (numModules.x * numModules.y) > 1) { + dataProcessor[0]->CreateVirtualFile( + filePath, fileName, fileIndex, overwriteEnable, silentMode, + modulePos, numUDPInterfaces, framesPerFile, + numberOfTotalFrames, dynamicRange, numModules.x, + numModules.y, &hdf5LibMutex); + } + // link file in master + if (masterFileWriteEnable) { + dataProcessor[0]->LinkDataInMasterFile( + masterFileName, silentMode, &hdf5LibMutex); + } } - } #endif + } catch (...) { + ; // ignore it and just print it + } } void Implementation::StartRunning() { diff --git a/slsReceiverSoftware/src/Implementation.h b/slsReceiverSoftware/src/Implementation.h index fdd970139..c792430e5 100644 --- a/slsReceiverSoftware/src/Implementation.h +++ b/slsReceiverSoftware/src/Implementation.h @@ -387,5 +387,6 @@ class Implementation : private virtual slsDetectorDefs { std::vector> fifo; Arping arping; - std::mutex hdf5Lib; + // mutex shared across all hdf5 virtual, master and data files + std::mutex hdf5LibMutex; }; diff --git a/slsReceiverSoftware/src/MasterAttributes.cpp b/slsReceiverSoftware/src/MasterAttributes.cpp index e68de7dd7..f57c8aab6 100644 --- a/slsReceiverSoftware/src/MasterAttributes.cpp +++ b/slsReceiverSoftware/src/MasterAttributes.cpp @@ -2,22 +2,21 @@ // Copyright (C) 2021 Contributors to the SLS Detector Package #include "MasterAttributes.h" -#include - -void MasterAttributes::WriteMasterBinaryAttributes(FILE *fd) { +void MasterAttributes::GetSpecificBinaryAttributes( + rapidjson::Writer *w) { LOG(logERROR) << "WriteMasterBinaryAttributes should have been called " "by a child class"; } -void MasterAttributes::GetBinaryMasterAttributes( +void MasterAttributes::GetCommonBinaryAttributes( rapidjson::Writer *w) { - time_t t = time(nullptr); w->Key("Version"); w->SetMaxDecimalPlaces(2); w->Double(BINARY_WRITER_VERSION); w->Key("Timestamp"); + time_t t = time(nullptr); w->String(ctime(&t)); w->Key("Detector Type"); @@ -61,15 +60,7 @@ void MasterAttributes::GetBinaryMasterAttributes( w->Uint64(totalFrames); }; -void MasterAttributes::WriteBinaryAttributes(FILE *fd, std::string message) { - if (fwrite((void *)message.c_str(), 1, message.length(), fd) != - message.length()) { - throw sls::RuntimeError( - "Master binary file incorrect number of bytes written to file"); - } -}; - -void MasterAttributes::WriteFinalBinaryAttributes( +void MasterAttributes::GetFinalBinaryAttributes( rapidjson::Writer *w) { // adding few common parameters to the end @@ -309,25 +300,15 @@ void MasterAttributes::WriteHDF5Attributes(H5File *fd, Group *group) { }; #endif - void GotthardMasterAttributes::WriteMasterBinaryAttributes(FILE *fd) { - rapidjson::StringBuffer s; - rapidjson::Writer writer(s); - writer.StartObject(); - MasterAttributes::GetBinaryMasterAttributes(&writer); - - writer.Key("Exptime"); - writer.String(sls::ToString(exptime).c_str()); + void GotthardMasterAttributes::GetSpecificBinaryAttributes(rapidjson::Writer *w) { + w->Key("Exptime"); + w->String(sls::ToString(exptime).c_str()); - writer.Key("Period"); - writer.String(sls::ToString(period).c_str()); + w->Key("Period"); + w->String(sls::ToString(period).c_str()); - writer.Key("Roi (xmin, xmax)"); - writer.String(sls::ToString(roi).c_str()); - - MasterAttributes::WriteFinalBinaryAttributes(&writer); - writer.EndObject(); - std::string message = s.GetString(); - MasterAttributes::WriteBinaryAttributes(fd, message); + w->Key("Roi (xmin, xmax)"); + w->String(sls::ToString(roi).c_str()); }; #ifdef HDF5C @@ -349,31 +330,22 @@ void MasterAttributes::WriteHDF5Attributes(H5File *fd, Group *group) { "roi xmax", PredType::NATIVE_INT, dataspace); dataset.write(&roi.xmax, PredType::NATIVE_INT); } + MasterAttributes::WriteFinalHDF5Attributes(fd, group); }; #endif - void JungfrauMasterAttributes::WriteMasterBinaryAttributes(FILE *fd) { - rapidjson::StringBuffer s; - rapidjson::Writer writer(s); - writer.StartObject(); - MasterAttributes::GetBinaryMasterAttributes(&writer); - - writer.Key("Exptime"); - writer.String(sls::ToString(exptime).c_str()); + void JungfrauMasterAttributes::GetSpecificBinaryAttributes(rapidjson::Writer *w) { + w->Key("Exptime"); + w->String(sls::ToString(exptime).c_str()); - writer.Key("Period"); - writer.String(sls::ToString(period).c_str()); + w->Key("Period"); + w->String(sls::ToString(period).c_str()); - writer.Key("Number of UDP Interfaces"); - writer.Uint(numUDPInterfaces); + w->Key("Number of UDP Interfaces"); + w->Uint(numUDPInterfaces); - writer.Key("Number of rows"); - writer.Uint(readNRows); - - MasterAttributes::WriteFinalBinaryAttributes(&writer); - writer.EndObject(); - std::string message = s.GetString(); - MasterAttributes::WriteBinaryAttributes(fd, message); + w->Key("Number of rows"); + w->Uint(readNRows); }; #ifdef HDF5C @@ -394,49 +366,40 @@ void MasterAttributes::WriteHDF5Attributes(H5File *fd, Group *group) { "Number of rows", PredType::NATIVE_INT, dataspace); dataset.write(&readNRows, PredType::NATIVE_INT); } + MasterAttributes::WriteFinalHDF5Attributes(fd, group); }; #endif - void EigerMasterAttributes::WriteMasterBinaryAttributes(FILE *fd) { - rapidjson::StringBuffer s; - rapidjson::Writer writer(s); - writer.StartObject(); - MasterAttributes::GetBinaryMasterAttributes(&writer); + void EigerMasterAttributes::GetSpecificBinaryAttributes(rapidjson::Writer *w) { + w->Key("Dynamic Range"); + w->Uint(dynamicRange); - writer.Key("Dynamic Range"); - writer.Uint(dynamicRange); + w->Key("Ten Giga"); + w->Uint(tenGiga); - writer.Key("Ten Giga"); - writer.Uint(tenGiga); - - writer.Key("Exptime"); - writer.String(sls::ToString(exptime).c_str()); + w->Key("Exptime"); + w->String(sls::ToString(exptime).c_str()); - writer.Key("Period"); - writer.String(sls::ToString(period).c_str()); + w->Key("Period"); + w->String(sls::ToString(period).c_str()); - writer.Key("Threshold Energy"); - writer.Int(thresholdEnergyeV); + w->Key("Threshold Energy"); + w->Int(thresholdEnergyeV); - writer.Key("Sub Exptime"); - writer.String(sls::ToString(subExptime).c_str()); + w->Key("Sub Exptime"); + w->String(sls::ToString(subExptime).c_str()); - writer.Key("Sub Period"); - writer.String(sls::ToString(subPeriod).c_str()); + w->Key("Sub Period"); + w->String(sls::ToString(subPeriod).c_str()); - writer.Key("Quad"); - writer.Int(quad); + w->Key("Quad"); + w->Int(quad); - writer.Key("Number of rows"); - writer.Int(readNRows); + w->Key("Number of rows"); + w->Int(readNRows); - writer.Key("Rate Corrections"); - writer.String(sls::ToString(ratecorr).c_str()); - - MasterAttributes::WriteFinalBinaryAttributes(&writer); - writer.EndObject(); - std::string message = s.GetString(); - MasterAttributes::WriteBinaryAttributes(fd, message); + w->Key("Rate Corrections"); + w->String(sls::ToString(ratecorr).c_str()); }; #ifdef HDF5C @@ -502,55 +465,46 @@ void MasterAttributes::WriteHDF5Attributes(H5File *fd, Group *group) { sls::strcpy_safe(c, sls::ToString(ratecorr)); dataset.write(c, strdatatype); } + MasterAttributes::WriteFinalHDF5Attributes(fd, group); }; #endif - void Mythen3MasterAttributes::WriteMasterBinaryAttributes(FILE *fd) { - rapidjson::StringBuffer s; - rapidjson::Writer writer(s); - writer.StartObject(); - MasterAttributes::GetBinaryMasterAttributes(&writer); + void Mythen3MasterAttributes::GetSpecificBinaryAttributes(rapidjson::Writer *w) { + w->Key("Dynamic Range"); + w->Uint(dynamicRange); - writer.Key("Dynamic Range"); - writer.Uint(dynamicRange); + w->Key("Ten Giga"); + w->Uint(tenGiga); - writer.Key("Ten Giga"); - writer.Uint(tenGiga); + w->Key("Period"); + w->String(sls::ToString(period).c_str()); - writer.Key("Period"); - writer.String(sls::ToString(period).c_str()); + w->Key("Counter Mask"); + w->String(sls::ToStringHex(counterMask).c_str()); - writer.Key("Counter Mask"); - writer.String(sls::ToStringHex(counterMask).c_str()); - - writer.Key("Exptime1"); - writer.String(sls::ToString(exptime1).c_str()); + w->Key("Exptime1"); + w->String(sls::ToString(exptime1).c_str()); - writer.Key("Exptime2"); - writer.String(sls::ToString(exptime2).c_str()); + w->Key("Exptime2"); + w->String(sls::ToString(exptime2).c_str()); - writer.Key("Exptime3"); - writer.String(sls::ToString(exptime3).c_str()); + w->Key("Exptime3"); + w->String(sls::ToString(exptime3).c_str()); - writer.Key("GateDelay1"); - writer.String(sls::ToString(gateDelay1).c_str()); + w->Key("GateDelay1"); + w->String(sls::ToString(gateDelay1).c_str()); - writer.Key("GateDelay2"); - writer.String(sls::ToString(gateDelay2).c_str()); + w->Key("GateDelay2"); + w->String(sls::ToString(gateDelay2).c_str()); - writer.Key("GateDelay3"); - writer.String(sls::ToString(gateDelay3).c_str()); + w->Key("GateDelay3"); + w->String(sls::ToString(gateDelay3).c_str()); - writer.Key("Gates"); - writer.Uint(gates); + w->Key("Gates"); + w->Uint(gates); - writer.Key("Threshold Energies"); - writer.String(sls::ToString(thresholdAllEnergyeV).c_str()); - - MasterAttributes::WriteFinalBinaryAttributes(&writer); - writer.EndObject(); - std::string message = s.GetString(); - MasterAttributes::WriteBinaryAttributes(fd, message); + w->Key("Threshold Energies"); + w->String(sls::ToString(thresholdAllEnergyeV).c_str()); }; #ifdef HDF5C @@ -638,28 +592,19 @@ void MasterAttributes::WriteHDF5Attributes(H5File *fd, Group *group) { sls::strcpy_safe(c, sls::ToString(thresholdAllEnergyeV)); dataset.write(c, strdatatype); } + MasterAttributes::WriteFinalHDF5Attributes(fd, group); }; #endif - void Gotthard2MasterAttributes::WriteMasterBinaryAttributes(FILE *fd) { - rapidjson::StringBuffer s; - rapidjson::Writer writer(s); - writer.StartObject(); - MasterAttributes::GetBinaryMasterAttributes(&writer); - - writer.Key("Exptime"); - writer.String(sls::ToString(exptime).c_str()); + void Gotthard2MasterAttributes::GetSpecificBinaryAttributes(rapidjson::Writer *w) { + w->Key("Exptime"); + w->String(sls::ToString(exptime).c_str()); - writer.Key("Period"); - writer.String(sls::ToString(period).c_str()); + w->Key("Period"); + w->String(sls::ToString(period).c_str()); - writer.Key("Burst Mode"); - writer.String(sls::ToString(burstMode).c_str()); - - MasterAttributes::WriteFinalBinaryAttributes(&writer); - writer.EndObject(); - std::string message = s.GetString(); - MasterAttributes::WriteBinaryAttributes(fd, message); + w->Key("Burst Mode"); + w->String(sls::ToString(burstMode).c_str()); }; #ifdef HDF5C @@ -678,34 +623,25 @@ void MasterAttributes::WriteHDF5Attributes(H5File *fd, Group *group) { sls::strcpy_safe(c, sls::ToString(burstMode)); dataset.write(c, strdatatype); } + MasterAttributes::WriteFinalHDF5Attributes(fd, group); }; #endif - void MoenchMasterAttributes::WriteMasterBinaryAttributes(FILE *fd) { - rapidjson::StringBuffer s; - rapidjson::Writer writer(s); - writer.StartObject(); - MasterAttributes::GetBinaryMasterAttributes(&writer); - - writer.Key("Exptime"); - writer.String(sls::ToString(exptime).c_str()); + void MoenchMasterAttributes::GetSpecificBinaryAttributes(rapidjson::Writer *w) { + w->Key("Exptime"); + w->String(sls::ToString(exptime).c_str()); - writer.Key("Period"); - writer.String(sls::ToString(period).c_str()); + w->Key("Period"); + w->String(sls::ToString(period).c_str()); - writer.Key("Ten Giga"); - writer.Uint(tenGiga); + w->Key("Ten Giga"); + w->Uint(tenGiga); - writer.Key("ADC Mask"); - writer.String(sls::ToStringHex(adcmask).c_str()); + w->Key("ADC Mask"); + w->String(sls::ToStringHex(adcmask).c_str()); - writer.Key("Analog Samples"); - writer.Uint(analogSamples); - - MasterAttributes::WriteFinalBinaryAttributes(&writer); - writer.EndObject(); - std::string message = s.GetString(); - MasterAttributes::WriteBinaryAttributes(fd, message); + w->Key("Analog Samples"); + w->Uint(analogSamples); }; #ifdef HDF5C @@ -728,49 +664,40 @@ void MasterAttributes::WriteHDF5Attributes(H5File *fd, Group *group) { "Analog Samples", PredType::NATIVE_INT, dataspace); dataset.write(&analogSamples, PredType::NATIVE_INT); } + MasterAttributes::WriteFinalHDF5Attributes(fd, group); }; #endif - void CtbMasterAttributes::WriteMasterBinaryAttributes(FILE *fd) { - rapidjson::StringBuffer s; - rapidjson::Writer writer(s); - writer.StartObject(); - MasterAttributes::GetBinaryMasterAttributes(&writer); - - writer.Key("Exptime"); - writer.String(sls::ToString(exptime).c_str()); + void CtbMasterAttributes::GetSpecificBinaryAttributes(rapidjson::Writer *w) { + w->Key("Exptime"); + w->String(sls::ToString(exptime).c_str()); - writer.Key("Period"); - writer.String(sls::ToString(period).c_str()); + w->Key("Period"); + w->String(sls::ToString(period).c_str()); - writer.Key("Ten Giga"); - writer.Uint(tenGiga); + w->Key("Ten Giga"); + w->Uint(tenGiga); - writer.Key("ADC Mask"); - writer.String(sls::ToStringHex(adcmask).c_str()); + w->Key("ADC Mask"); + w->String(sls::ToStringHex(adcmask).c_str()); - writer.Key("Analog Flag"); - writer.Uint(analog); + w->Key("Analog Flag"); + w->Uint(analog); - writer.Key("Analog Samples"); - writer.Uint(analogSamples); + w->Key("Analog Samples"); + w->Uint(analogSamples); - writer.Key("Digital Flag"); - writer.Uint(digital); + w->Key("Digital Flag"); + w->Uint(digital); - writer.Key("Digital Samples"); - writer.Uint(digitalSamples); + w->Key("Digital Samples"); + w->Uint(digitalSamples); - writer.Key("Dbit Offset"); - writer.Uint(dbitoffset); + w->Key("Dbit Offset"); + w->Uint(dbitoffset); - writer.Key("Dbit Bitset"); - writer.Uint64(dbitlist); - - MasterAttributes::WriteFinalBinaryAttributes(&writer); - writer.EndObject(); - std::string message = s.GetString(); - MasterAttributes::WriteBinaryAttributes(fd, message); + w->Key("Dbit Bitset"); + w->Uint64(dbitlist); }; #ifdef HDF5C @@ -828,5 +755,6 @@ void MasterAttributes::WriteHDF5Attributes(H5File *fd, Group *group) { "Dbit Bitset List", PredType::STD_U64LE, dataspace); dataset.write(&dbitlist, PredType::STD_U64LE); } + MasterAttributes::WriteFinalHDF5Attributes(fd, group); }; #endif diff --git a/slsReceiverSoftware/src/MasterAttributes.h b/slsReceiverSoftware/src/MasterAttributes.h index 58a29e8a9..27c7ba13b 100644 --- a/slsReceiverSoftware/src/MasterAttributes.h +++ b/slsReceiverSoftware/src/MasterAttributes.h @@ -7,6 +7,7 @@ #include "sls/logger.h" #include "sls/sls_detector_defs.h" +#include #include #ifdef HDF5C @@ -69,12 +70,12 @@ class MasterAttributes { MasterAttributes() = default; virtual ~MasterAttributes() = default; - virtual void WriteMasterBinaryAttributes(FILE *fd); + virtual void + GetSpecificBinaryAttributes(rapidjson::Writer *w); void - GetBinaryMasterAttributes(rapidjson::Writer *w); - void WriteBinaryAttributes(FILE *fd, std::string message); + GetCommonBinaryAttributes(rapidjson::Writer *w); void - WriteFinalBinaryAttributes(rapidjson::Writer *w); + GetFinalBinaryAttributes(rapidjson::Writer *w); #ifdef HDF5C virtual void WriteMasterHDF5Attributes(H5File *fd, Group *group); void WriteHDF5Attributes(H5File *fd, Group *group); @@ -89,7 +90,8 @@ class MasterAttributes { class GotthardMasterAttributes : public MasterAttributes { public: GotthardMasterAttributes() = default; - void WriteMasterBinaryAttributes(FILE *fd) override; + void GetSpecificBinaryAttributes( + rapidjson::Writer *w) override; #ifdef HDF5C void WriteMasterHDF5Attributes(H5File *fd, Group *group) override; #endif @@ -98,7 +100,8 @@ class GotthardMasterAttributes : public MasterAttributes { class JungfrauMasterAttributes : public MasterAttributes { public: JungfrauMasterAttributes() = default; - void WriteMasterBinaryAttributes(FILE *fd) override; + void GetSpecificBinaryAttributes( + rapidjson::Writer *w) override; #ifdef HDF5C void WriteMasterHDF5Attributes(H5File *fd, Group *group) override; #endif @@ -107,7 +110,8 @@ class JungfrauMasterAttributes : public MasterAttributes { class EigerMasterAttributes : public MasterAttributes { public: EigerMasterAttributes() = default; - void WriteMasterBinaryAttributes(FILE *fd) override; + void GetSpecificBinaryAttributes( + rapidjson::Writer *w) override; #ifdef HDF5C void WriteMasterHDF5Attributes(H5File *fd, Group *group) override; #endif @@ -116,7 +120,8 @@ class EigerMasterAttributes : public MasterAttributes { class Mythen3MasterAttributes : public MasterAttributes { public: Mythen3MasterAttributes() = default; - void WriteMasterBinaryAttributes(FILE *fd) override; + void GetSpecificBinaryAttributes( + rapidjson::Writer *w) override; #ifdef HDF5C void WriteMasterHDF5Attributes(H5File *fd, Group *group) override; #endif @@ -125,7 +130,8 @@ class Mythen3MasterAttributes : public MasterAttributes { class Gotthard2MasterAttributes : public MasterAttributes { public: Gotthard2MasterAttributes() = default; - void WriteMasterBinaryAttributes(FILE *fd) override; + void GetSpecificBinaryAttributes( + rapidjson::Writer *w) override; #ifdef HDF5C void WriteMasterHDF5Attributes(H5File *fd, Group *group) override; #endif @@ -134,7 +140,8 @@ class Gotthard2MasterAttributes : public MasterAttributes { class MoenchMasterAttributes : public MasterAttributes { public: MoenchMasterAttributes() = default; - void WriteMasterBinaryAttributes(FILE *fd) override; + void GetSpecificBinaryAttributes( + rapidjson::Writer *w) override; #ifdef HDF5C void WriteMasterHDF5Attributes(H5File *fd, Group *group) override; #endif @@ -143,7 +150,8 @@ class MoenchMasterAttributes : public MasterAttributes { class CtbMasterAttributes : public MasterAttributes { public: CtbMasterAttributes() = default; - void WriteMasterBinaryAttributes(FILE *fd) override; + void GetSpecificBinaryAttributes( + rapidjson::Writer *w) override; #ifdef HDF5C void WriteMasterHDF5Attributes(H5File *fd, Group *group) override; #endif