170 lines
4.5 KiB
C++
170 lines
4.5 KiB
C++
#include "IO/PIO.h"
|
|
#include "common/Utilities.h"
|
|
#include "common/MPI.h"
|
|
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <cstring>
|
|
|
|
|
|
namespace IO {
|
|
|
|
|
|
static ParallelStreamBuffer pout_buffer;
|
|
static ParallelStreamBuffer perr_buffer;
|
|
static ParallelStreamBuffer plog_buffer;
|
|
|
|
|
|
std::ostream pout(&pout_buffer);
|
|
std::ostream perr(&perr_buffer);
|
|
std::ostream plog(&plog_buffer);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* Functions to control logging *
|
|
****************************************************************************/
|
|
std::ofstream *global_filestream=NULL;
|
|
static void shutdownFilestream( )
|
|
{
|
|
if ( global_filestream!=NULL ) {
|
|
global_filestream->flush();
|
|
global_filestream->close();
|
|
delete global_filestream;
|
|
global_filestream = NULL;
|
|
}
|
|
}
|
|
void Utilities::logOnlyNodeZero( const std::string &filename )
|
|
{
|
|
int rank = 0;
|
|
#ifdef USE_MPI
|
|
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
|
|
#endif
|
|
if ( rank == 0 )
|
|
logAllNodes(filename,true);
|
|
}
|
|
void Utilities::logAllNodes( const std::string &filename, bool singleStream )
|
|
{
|
|
if ( singleStream )
|
|
ERROR("Not implimented yet");
|
|
|
|
// If the filestream was open, then close it and reset streams
|
|
shutdownFilestream();
|
|
|
|
// Open the log stream and redirect output
|
|
std::string full_filename = filename;
|
|
if ( !singleStream ) {
|
|
int rank = 0;
|
|
#ifdef USE_MPI
|
|
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
|
|
#endif
|
|
char tmp[100];
|
|
sprintf(tmp,".%04i",rank);
|
|
full_filename += std::string(tmp);
|
|
}
|
|
global_filestream = new std::ofstream(full_filename.c_str());
|
|
|
|
if ( !(*global_filestream) ) {
|
|
delete global_filestream;
|
|
global_filestream = NULL;
|
|
perr << "PIO: Could not open log file ``" << full_filename << "''\n";
|
|
} else {
|
|
pout_buffer.setOutputStream(global_filestream);
|
|
pout_buffer.setOutputStream(&std::cout);
|
|
perr_buffer.setOutputStream(global_filestream);
|
|
perr_buffer.setOutputStream(&std::cerr);
|
|
plog_buffer.setOutputStream(global_filestream);
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* ParallelStreamBuffer class *
|
|
****************************************************************************/
|
|
void Utilities::stopLogging( )
|
|
{
|
|
pout_buffer.reset();
|
|
perr_buffer.reset();
|
|
plog_buffer.reset();
|
|
shutdownFilestream();
|
|
delete global_filestream;
|
|
global_filestream = NULL;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* ParallelStreamBuffer class *
|
|
****************************************************************************/
|
|
ParallelStreamBuffer::ParallelStreamBuffer( ):
|
|
d_rank(0), d_size(0), d_buffer_size(0), d_buffer(NULL)
|
|
{
|
|
}
|
|
ParallelStreamBuffer:: ~ParallelStreamBuffer()
|
|
{
|
|
delete [] d_buffer;
|
|
}
|
|
void ParallelStreamBuffer::setOutputStream( std::ostream *stream )
|
|
{
|
|
d_stream.push_back( stream );
|
|
}
|
|
int ParallelStreamBuffer::sync()
|
|
{
|
|
for (size_t i=0; i<d_stream.size(); i++) {
|
|
std::ostream& stream = *d_stream[i];
|
|
stream << d_buffer;
|
|
}
|
|
d_size = 0;
|
|
memset(d_buffer,0,d_buffer_size);
|
|
return 0;
|
|
}
|
|
void ParallelStreamBuffer::reserve( size_t size )
|
|
{
|
|
if ( size > d_buffer_size ) {
|
|
if ( d_buffer_size==0 ) {
|
|
d_buffer_size = 1024;
|
|
d_buffer = new char[d_buffer_size];
|
|
memset(d_buffer,0,d_buffer_size);
|
|
}
|
|
while ( size > d_buffer_size ) {
|
|
char *tmp = d_buffer;
|
|
d_buffer_size *= 2;
|
|
d_buffer = new char[d_buffer_size];
|
|
memset(d_buffer,0,d_buffer_size);
|
|
memcpy(d_buffer,tmp,d_size);
|
|
delete [] tmp;
|
|
}
|
|
}
|
|
}
|
|
std::streamsize ParallelStreamBuffer::xsputn( const char* text, std::streamsize n )
|
|
{
|
|
reserve(d_size+n);
|
|
memcpy(&d_buffer[d_size],text,n);
|
|
d_size += n;
|
|
if ( text[n-1]==0 || text[n-1]==10 ) { sync(); }
|
|
return n;
|
|
}
|
|
int ParallelStreamBuffer::overflow(int ch)
|
|
{
|
|
reserve(d_size+1);
|
|
d_buffer[d_size] = ch;
|
|
d_size++;
|
|
if ( ch==0 || ch==10 ) { sync(); }
|
|
return std::char_traits<char>::to_int_type(ch);
|
|
}
|
|
int ParallelStreamBuffer::underflow()
|
|
{
|
|
return -1;
|
|
}
|
|
void ParallelStreamBuffer::reset()
|
|
{
|
|
sync();
|
|
d_stream.clear();
|
|
delete [] d_buffer;
|
|
d_buffer = NULL;
|
|
d_buffer_size = 0;
|
|
}
|
|
|
|
|
|
} // IO namespace
|
|
|