/* * asymRootManager.cpp * * Created on: October 30, 2025 * Author: Hovanes Egiyan * * Modified on: * */ #include "asymRootManager.hh" #include "asymRootFile.hh" asymRootManager* asymRootManager::selfPtr = 0; //Int_t asymRootManager::prmCompressFactor = 1; // no compression Int_t asymRootManager::prmCompressFactor = 509; // high compression using LZ4 //Int_t asymRootManager::prmCompressFactor = 609; // high compression using ZSTD std::queue asymRootManager::prmBuffer; UInt_t asymRootFile::prfTreeBuffSize = static_cast( 1 << 16 ); UInt_t asymRootFile::prfAutoSaveSize = static_cast( 1 << 30 ); string asymRootFile::prfBranchName = "record"; // constructor asymRootManager::asymRootManager() : prmPrefix( "" ), prmSuffix( "" ), prmThread( 0 ), prmStop( true ), prmFile( 0 ), prmDir( "" ), prmFileName( "nofile" ), prmFileLimit( 0x40000000 ), prmFileSize( 0 ) { // reinitialize self pointer if ( selfPtr != 0 ) delete selfPtr; selfPtr = this; // clear FIFO while ( prmBuffer.size() > 0 ) prmBuffer.pop(); // Create mutex for buffer operation if ( prmMutex ) delete prmMutex; pthread_mutexattr_t attr; pthread_mutexattr_init( &attr ); pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK ); prmMutex = new pthread_mutex_t; pthread_mutex_init( prmMutex, &attr ); return; } // destructor asymRootManager::~asymRootManager() { if ( prmFile != 0 && prmFile->IsOpen() ) { prmFile->Close(); prmFile = 0; } selfPtr = 0; return; } void asymRootManager::StartDAQ( string dir, string prefix, string suffix, long nlim ) { prmDir = dir; prmPrefix = prefix; prmSuffix = suffix; prmFileLimit = nlim; prmStop = false; pthread_create( &prmThread, NULL, WriteThread, (void*) this ); return; } void asymRootManager::NewRootFile() { // new filename TDatime dtTime; TString rsTime( dtTime.AsSQLString() ); rsTime.ReplaceAll( " ", "_" ); rsTime.ReplaceAll( ":", "" ); rsTime.ReplaceAll( "-", "" ); prmFileName = prmPrefix + string( rsTime.Data() ) + prmSuffix + ".root"; string fullpath = prmDir + prmFileName; prmFile = new asymRootFile( fullpath.c_str(), "RECREATE", "ASYM ROOT File", prmCompressFactor ); } void asymRootManager::WriteFile( const char* channelName, struct timespec* timeStamp, long* buffPtr, int nElm, short& helScheme, float& flipFreq, float& stableTime ) { recordBuffer tmprecord( string( channelName ), asymRootRecord( *timeStamp, nElm, buffPtr, helScheme, flipFreq, stableTime ) ); // push to buffer pthread_mutex_lock( prmMutex ); prmBuffer.push( tmprecord ); pthread_mutex_unlock( prmMutex ); return; } void asymRootManager::CloseFile() { prmStop = true; if ( prmThread ) { pthread_join( prmThread, NULL ); prmThread = 0; } } void *WriteThread( void *argument ) { // sleep timer struct timespec sleeptime; sleeptime.tv_sec = 0; sleeptime.tv_nsec = (long int) (0.01 * 1.e9); asymRootManager *prmPtr = (asymRootManager*) argument; // CLose Existing Root file if ( prmPtr->prmFile != 0 && prmPtr->prmFile->IsOpen() ) prmPtr->prmFile->Close(); while ( !prmPtr->prmStop ) { // read buffer if non-empty if ( prmPtr->prmBuffer.size() ) { pthread_mutex_lock( prmPtr->prmMutex ); recordBuffer tmprecord = prmPtr->prmBuffer.front(); prmPtr->prmBuffer.pop(); pthread_mutex_unlock( prmPtr->prmMutex ); // check if file open if ( prmPtr->prmFile == 0 || !prmPtr->prmFile->IsOpen() ) { prmPtr->NewRootFile(); } // write to disk prmPtr->prmFile->FillTree( tmprecord.treename, tmprecord.record ); // check file size, close if larger than tolerance prmPtr->prmFileSize = prmPtr->prmFile->GetEND(); if ( prmPtr->prmFileSize >= prmPtr->prmFileLimit ) { prmPtr->prmFile->Close(); } } else nanosleep( &sleeptime, &sleeptime ); } // clear buffer while ( prmPtr->prmBuffer.size() ) { pthread_mutex_lock( prmPtr->prmMutex ); recordBuffer tmprecord = prmPtr->prmBuffer.front(); prmPtr->prmBuffer.pop(); pthread_mutex_unlock( prmPtr->prmMutex ); // check if file open if ( prmPtr->prmFile == 0 || !prmPtr->prmFile->IsOpen() ) { prmPtr->NewRootFile(); } // write to disk prmPtr->prmFile->FillTree( tmprecord.treename, tmprecord.record ); } if ( prmPtr->prmFile != 0 && prmPtr->prmFile->IsOpen() ) prmPtr->prmFile->Close(); prmPtr->prmFile = 0; prmPtr->prmFileName = string( "nofile" ); prmPtr->prmFileSize = 0; return NULL; } extern "C" { #include "asymRootManager.h" void StartRootDAQ( const char* dir, const char* prefix, const char* suffix, long nlim ) { string strdir( dir ); string strpfx( prefix ); string strsfx( suffix ); asymRootManager::GetInstance()->StartDAQ( strdir, strpfx, strsfx, nlim ); return; } void CloseRootFile() { asymRootManager::GetInstance()->CloseFile(); return; } void WriteRootFile( const char* channelName, struct timespec* timeStamp, long* buffPtr, int nElm, short *helScheme, float *flipFreq, float *stableTime ) { asymRootManager::GetInstance()->WriteFile( channelName, timeStamp, buffPtr, nElm, *helScheme, *flipFreq, *stableTime ); return; } int GetBufferSize() { return asymRootManager::GetInstance()->prmBuffer.size(); } const char* GetFileName() { return asymRootManager::GetInstance()->prmFileName.c_str(); } long GetFileSize() { return asymRootManager::GetInstance()->prmFileSize; } } ;