Skip to content

Commit

Permalink
FileEventDataListener does the loading in a separate thread....
Browse files Browse the repository at this point in the history
so that it happens between calls to extractData. Re #4812.
Once the whole file is read, an exception is thrown to stop the
calling algorithm.
  • Loading branch information
RussellTaylor committed Feb 27, 2012
1 parent 9f46628 commit a764b6e
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/ILiveListener.h"
#include "MantidAPI/Algorithm.h"
#include "MantidDataObjects/EventWorkspace.h"
#include <Poco/ActiveMethod.h>
#include <Poco/Void.h>
Expand Down Expand Up @@ -57,12 +58,14 @@ namespace Mantid

private:
const std::string m_filename; ///< The file to read
int m_numChunks; ///< The number of pieces to divide the file into
int m_numChunks; ///< The number of pieces to divide the file into
int m_nextChunk; ///< The number of the next chunk to be loaded
DataObjects::EventWorkspace_sptr m_buffer; ///< Used to buffer events between calls to extractData()

// Poco::ActiveMethod<API::MatrixWorkspace_sptr, Poco::Void, FileEventDataListener> m_loadChunk;
API::MatrixWorkspace_sptr loadChunkImpl(Poco::Void);
/// Future that holds the result of the latest call to LoadEventPreNexus
Poco::ActiveResult<bool> * m_chunkload;
void loadChunk();
/// Shared pointer to the LoadEventPreNexus instance - it needs to be kept alive.
API::Algorithm_sptr m_loader;

static Kernel::Logger& g_log; ///< reference to the logger class
};
Expand Down
54 changes: 37 additions & 17 deletions Code/Mantid/Framework/DataHandling/src/FileEventDataListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ namespace DataHandling
/// Constructor
FileEventDataListener::FileEventDataListener() : ILiveListener(),
m_filename(ConfigService::Instance().getString("fileeventdatalistener.filename")),
m_nextChunk(1),
m_buffer()//, m_loadChunk(this,&FileEventDataListener::loadChunkImpl)
m_nextChunk(1), m_chunkload(NULL)
{
if ( m_filename.empty() ) g_log.error("Configuration property fileeventdatalistener.filename not found");

Expand All @@ -32,6 +31,12 @@ namespace DataHandling
/// Destructor
FileEventDataListener::~FileEventDataListener()
{
// Don't disappear until any running job has finished or bad things happen!
if ( m_chunkload ) m_chunkload->wait();
// Clean up the hidden workspace
AnalysisDataService::Instance().remove("__filelistenerchunk");
// Don't leak memory
delete m_chunkload;
}

bool FileEventDataListener::connect(const Poco::Net::SocketAddress&)
Expand All @@ -47,29 +52,44 @@ namespace DataHandling

void FileEventDataListener::start(Kernel::DateAndTime /*startTime*/) // Ignore the start time
{
// Kick off loading the first chunk (which will include loading the instrument etc.)
loadChunk();
return;
}

boost::shared_ptr<MatrixWorkspace> FileEventDataListener::extractData()
{
// For now, the load algorithm will just fail once it gets to the end of the file
return loadChunkImpl(Poco::Void());
// Once the end of the file is reached, this method throws to stop the calling algorithm.
// This is equivalent to the end of the run - which we still need to figure out how to handle.
if ( m_chunkload == NULL ) throw std::runtime_error("The whole file has been read!");

// If the loading of the chunk isn't finished, then we need to wait
m_chunkload->wait();
if ( ! m_chunkload->data() ) throw std::runtime_error("LoadEventPreNexus failed for some reason.");
// The loading succeeded: get the workspace from the ADS.
MatrixWorkspace_sptr chunk = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("__filelistenerchunk");
// Delete the ActiveResult to signify that we're done with it.
delete m_chunkload;
m_chunkload = NULL;
// Kick off the loading of the next chunk (unless we're at the end of the file)
if ( m_nextChunk <= m_numChunks ) loadChunk();

return chunk;
}

API::MatrixWorkspace_sptr FileEventDataListener::loadChunkImpl(Poco::Void)
/// Load the next chunk of data. Calls Algorithm::executeAsync to do it in another thread.
void FileEventDataListener::loadChunk()
{
Algorithm_sptr loader = AlgorithmManager::Instance().createUnmanaged("LoadEventPreNexus");
loader->initialize();
loader->setChild(true);
loader->setLogging(false);
loader->setPropertyValue("EventFilename",m_filename);
loader->setProperty("ChunkNumber",m_nextChunk++); // Increment
loader->setProperty("TotalChunks",m_numChunks);
loader->setPropertyValue("OutputWorkspace","anon"); // Fake name
loader->execute();

IEventWorkspace_sptr evWS = loader->getProperty("OutputWorkspace");
return evWS;
m_loader = AlgorithmManager::Instance().createUnmanaged("LoadEventPreNexus");
m_loader->initialize();
// loader->setChild(true); // It can't be a child because the output needs to go in the ADS
m_loader->setLogging(false);
m_loader->setPropertyValue("EventFilename",m_filename);
m_loader->setProperty("ChunkNumber",m_nextChunk++); // post-increment
m_loader->setProperty("TotalChunks",m_numChunks);
m_loader->setPropertyValue("OutputWorkspace","__filelistenerchunk"); // Goes into 'hidden' workspace
m_chunkload = new Poco::ActiveResult<bool>(m_loader->executeAsync());
}

} // namespace Mantid
} // namespace DataHandling

0 comments on commit a764b6e

Please sign in to comment.