163 lines
4.6 KiB
C++
163 lines
4.6 KiB
C++
#include "IO/PIO.h"
|
|
#include "common/MPI.h"
|
|
#include "common/Utilities.h"
|
|
|
|
#include <cstring>
|
|
#include <fstream>
|
|
#include <string>
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
} // namespace IO
|