Example #1
0
Log& Log::instance()
{
    Log* log = _logInstance.get();
    if( !log )
    {
        log = new Log();
        _logInstance = log;
        static bool first = true;
        if( first && lunchbox::Log::level > LOG_INFO )
        {
            first = false;
            log->disableHeader();
            log->disableFlush();
            *log << std::setw( LENGTH_PID ) << std::right << "PID" << "."
                 << std::setw( LENGTH_THREAD ) << std::left << "Thread " << "|"
                 << std::setw( LENGTH_FILE+5 ) << " Filename:line " << "|"
                 << std::right << std::setw( LENGTH_TIME ) << " ms " << "|"
                 << " Message" << std::endl;
            log->enableFlush();
            log->enableHeader();
        }
    }

    return *log;
}
Example #2
0
Log& Log::instance()
{
    Log* log = _logInstance.get();
    if( !log )
    {
        log = new Log();
        _logInstance = log;
    }

    return *log;
}
Example #3
0
    /**
     * Draws a bin. Most of this code is copied from osgUtil::RenderBin::drawImplementation.
     * The modifications are (a) skipping code to render child bins, (b) setting a bin-global
     * projection matrix in orthographic space, and (c) calling our custom "renderLeaf()" method 
     * instead of RenderLeaf::render()
     */
    void drawImplementation( osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous )
    {
        osg::State& state = *renderInfo.getState();

        unsigned int numToPop = (previous ? osgUtil::StateGraph::numToPop(previous->_parent) : 0);
        if (numToPop>1) --numToPop;
        unsigned int insertStateSetPosition = state.getStateSetStackSize() - numToPop;

        if (bin->getStateSet())
        {
            state.insertStateSet(insertStateSetPosition, bin->getStateSet());
        }

        // apply a window-space projection matrix.
        const osg::Viewport* vp = renderInfo.getCurrentCamera()->getViewport();
        if ( vp )
        {
            //TODO see which is faster

            osg::ref_ptr<osg::RefMatrix>& m = _ortho2D.get();
            if ( !m.valid() )
                m = new osg::RefMatrix();

            m->makeOrtho2D( vp->x(), vp->x()+vp->width()-1, vp->y(), vp->y()+vp->height()-1 );
            state.applyProjectionMatrix( m.get() );

            //osg::ref_ptr<osg::RefMatrix> rm = new osg::RefMatrix( osg::Matrix::ortho2D(
            //    vp->x(), vp->x()+vp->width()-1,
            //    vp->y(), vp->y()+vp->height()-1 ) );
            //state.applyProjectionMatrix( rm.get() );
        }

        // render the list
        osgUtil::RenderBin::RenderLeafList& leaves = bin->getRenderLeafList();
        for(osgUtil::RenderBin::RenderLeafList::reverse_iterator rlitr = leaves.rbegin();
            rlitr!= leaves.rend();
            ++rlitr)
        {
            osgUtil::RenderLeaf* rl = *rlitr;
            renderLeaf( rl, renderInfo, previous );
            previous = rl;
        }

        if ( bin->getStateSet() )
        {
            state.removeStateSet(insertStateSetPosition);
        }
    }
Example #4
0
namespace lunchbox
{
static unsigned getLogTopics();

namespace
{
class LogTable
{
public:
    LogTable( const LogLevel _level, const std::string& _name )
            : level( _level ), name( _name ) {}

    LogLevel level;
    std::string name;
};

#define LOG_TABLE_ENTRY( name ) LogTable( LOG_ ## name, std::string( #name ))
#define LOG_TABLE_SIZE (5)

static LogTable _logTable[ LOG_TABLE_SIZE ] =
{
    LOG_TABLE_ENTRY( ERROR ),
    LOG_TABLE_ENTRY( WARN ),
    LOG_TABLE_ENTRY( INFO ),
    LOG_TABLE_ENTRY( VERB ),
    LOG_TABLE_ENTRY( ALL )
};
}

int      Log::level  = Log::getLogLevel( getenv( "LB_LOG_LEVEL" ));
unsigned Log::topics = getLogTopics();
Clock    _defaultClock;
Clock*   _clock = &_defaultClock;
Lock     LogBuffer::_lock;

static PerThread< Log > _logInstance;

#ifdef NDEBUG
static std::ostream* _logStream = &std::cout;
#else
static std::ostream* _logStream = &std::cerr;
#endif
static std::ostream* _logFile = 0;

int Log::getLogLevel( const char* text )
{
    if( text )
    {
        const int num = atoi( text );
        if( num > 0 && num <= LOG_ALL )
            return num;

        for( uint32_t i = 0; i < LOG_TABLE_SIZE; ++i )
            if( _logTable[i].name == text )
                return _logTable[i].level;
    }

#ifdef NDEBUG
    return LOG_WARN;
#else
    return LOG_INFO;
#endif
}

std::string& Log::getLogLevelString()
{
    for( uint32_t i=0; i<LOG_TABLE_SIZE; ++i )
        if( _logTable[i].level == level )
                return _logTable[i].name;

    return _logTable[0].name;
}

unsigned getLogTopics()
{
    Log::level = Log::getLogLevel( getenv( "LB_LOG_LEVEL" ));
    const char *env = getenv( "LB_LOG_TOPICS" );

    if( env )
        return atoll(env);

    if( Log::level == LOG_ALL )
        return 0xffffffffu;

    return 0;
}

Log& Log::instance()
{
    Log* log = _logInstance.get();
    if( !log )
    {
        log = new Log();
        _logInstance = log;
    }

    return *log;
}

Log& Log::instance( const char* file, const int line )
{
    Log& log = instance();
    log.setLogInfo( file, line );
    return log;
}

void Log::exit()
{
    Log* log = _logInstance.get();
    _logInstance = 0;
    delete log;
}

void Log::reset()
{
    exit();

    delete _logFile;
    _logFile = 0;

#ifdef NDEBUG
    _logStream = &std::cout;
#else
    _logStream = &std::cerr;
#endif
}

void Log::setOutput( std::ostream& stream )
{
    _logStream = &stream;
    exit();
}

bool Log::setOutput( const std::string& file )
{
    std::ostream* oldLog = _logStream;
    std::ofstream* newLog = new std::ofstream( file.c_str( ));

    if( newLog->is_open( ))
    {
        setOutput( *newLog );
        *oldLog << "Redirected log to " << file << std::endl;

        delete _logFile;
        _logFile = newLog;
        return true;
    }

    LBWARN << "Can't open log file " << file << ": " << sysError << std::endl;
    delete newLog;
    return false;
}

void Log::setClock( Clock* clock )
{
    if( clock )
        _clock = clock;
    else
        _clock = &_defaultClock;
}

const Clock& Log::getClock()
{
    return *_clock;
}

std::ostream& Log::getOutput()
{
    return *_logStream;
}


void LogBuffer::setThreadName( const std::string& name )
{
    LBASSERT( !name.empty( ));
    snprintf( _thread, 12, "%s", name.c_str( ));
    _thread[11] = 0;
}

LogBuffer::int_type LogBuffer::overflow( LogBuffer::int_type c )
{
    if( c == EOF )
        return EOF;

    if( _newLine )
    {
        if( !_noHeader )
        {
            //assert( _thread[0] );
            _stringStream << getpid()  << " " << _thread << " " << _file << ":"
                          << _line << " " << _clock->getTime64() << " ";
        }

        for( int i=0; i<_indent; ++i )
            _stringStream << "    ";
        _newLine = false;
    }

    _stringStream << (char)c;
    return c;
}

int LogBuffer::sync()
{
    if( !_blocked )
    {
        const std::string& string = _stringStream.str();
        {
            ScopedMutex< Lock > mutex( _lock );
            _stream.write( string.c_str(), string.length( ));
            _stream.rdbuf()->pubsync();
        }
        _stringStream.str( "" );
    }
    _newLine = true;
    return 0;
}


std::ostream& indent( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->indent();
    return os;
}
std::ostream& exdent( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->exdent();
        return os;
}

std::ostream& disableFlush( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->disableFlush();
    return os;
}
std::ostream& enableFlush( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->enableFlush();
    return os;
}
std::ostream& forceFlush( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->forceFlush();
    return os;
}

std::ostream& disableHeader( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->disableHeader();
    return os;
}
std::ostream& enableHeader( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->enableHeader();
    return os;
}

}
Example #5
0
void Log::exit()
{
    Log* log = _logInstance.get();
    _logInstance = 0;
    delete log;
}
Example #6
0
namespace lunchbox
{
static unsigned getLogTopics();
static Clock    _defaultClock;
static Clock*   _clock = &_defaultClock;
static Lock     _lock; // The write lock

const size_t LENGTH_PID = 5;
const size_t LENGTH_THREAD = 8;
const size_t LENGTH_FILE = 29;
const size_t LENGTH_TIME = 6;

namespace detail
{
/** @internal The string buffer used for logging. */
class Log : public std::streambuf
{
public:
    explicit Log( std::ostream& stream )
        : _indent(0), _blocked(0), _noHeader(0),
          _newLine(true), _stream(stream)
    {
        _file[0] = 0;
        setThreadName( "Unknown" );
    }

    virtual ~Log() {}

    void indent() { ++_indent; }
    void exdent() { --_indent; }

    void disableFlush() { ++_blocked; assert( _blocked < 100 ); }
    void enableFlush()
    {
        assert( _blocked );// Too many enableFlush on log stream
        --_blocked;
    }

    void disableHeader() { ++_noHeader; } // use counted variable to allow
    void enableHeader()  { --_noHeader; } //   nested enable/disable calls

    void setThreadName( const std::string& name )
    {
        LBASSERT( !name.empty( ));
        _thread = name.substr( 0, LENGTH_THREAD );
    }

    const std::string& getThreadName() const { return _thread; }

    void setLogInfo( const char* f, const int line )
    {
        LBASSERT( f );
        std::string file( f );
        const size_t length = file.length();

        if( length > LENGTH_FILE )
            file = file.substr( length - LENGTH_FILE, length );

        snprintf( _file, LENGTH_FILE+6, "%29s:%-4d", file.c_str(), line );
    }

protected:
    int_type overflow( Log::int_type c ) override
    {
        if( c == EOF )
            return EOF;

        if( _newLine )
        {
            if( !_noHeader )
            {
                if( lunchbox::Log::level > LOG_INFO )
                    _stringStream << std::right << std::setw( LENGTH_PID )
                                  << getpid() << "."
                                  << std::left << std::setw( LENGTH_THREAD )
                                  << _thread << " " << _file << " "
                                  << std::right << std::setw( LENGTH_TIME )
                                  << _clock->getTime64() << " ";
                else
                    _stringStream << std::right << std::setw( LENGTH_TIME )
                                  << _clock->getTime64() << " ";
            }

            for( int i=0; i<_indent; ++i )
                _stringStream << "    ";
            _newLine = false;
        }

        _stringStream << (char)c;
        return c;
    }

    int sync() override
    {
        if( !_blocked )
        {
            const std::string& string = _stringStream.str();
            {
                ScopedMutex< lunchbox::Lock > mutex( _lock );
                _stream.write( string.c_str(), string.length( ));
                _stream.rdbuf()->pubsync();
            }
            _stringStream.str( "" );
        }
        _newLine = true;
        return 0;
    }

private:
    Log( const Log& );
    Log& operator = ( const Log& );

    /** Short thread name. */
    std::string _thread;

    /** The current file logging. */
    char _file[35];

    /** The current indentation level. */
    int _indent;

    /** Flush reference counter. */
    int _blocked;

    /** The header disable counter. */
    int _noHeader;

    /** The flag that a new line has started. */
    bool _newLine;

    /** The temporary buffer. */
    std::ostringstream _stringStream;

    /** The wrapped ostream. */
    std::ostream& _stream;
};
}

namespace
{
class LogTable
{
public:
    LogTable( const LogLevel _level, const std::string& _name )
            : level( _level ), name( _name ) {}

    LogLevel level;
    std::string name;
};

#define LOG_TABLE_ENTRY( name ) LogTable( LOG_ ## name, std::string( #name ))
#define LOG_TABLE_SIZE (6)

static LogTable _logTable[ LOG_TABLE_SIZE ] =
{
    LOG_TABLE_ENTRY( ERROR ),
    LogTable( LOG_ERROR, "WARN" ),
    LOG_TABLE_ENTRY( INFO ),
    LOG_TABLE_ENTRY( DEBUG ),
    LOG_TABLE_ENTRY( VERB ),
    LOG_TABLE_ENTRY( ALL )
};
}

int      Log::level  = Log::getLogLevel( getenv( "LB_LOG_LEVEL" ));
unsigned Log::topics = getLogTopics();

static PerThread< Log > _logInstance;

#ifdef NDEBUG
static std::ostream* _logStream = &std::cout;
#else
static std::ostream* _logStream = &std::cerr;
#endif
static std::ostream* _logFile = 0;

Log::Log()
    : std::ostream( new detail::Log( getOutput( )))
    , impl_( dynamic_cast< detail::Log* >( rdbuf( )))
{}

Log::~Log()
{
    impl_->pubsync();
    delete impl_;
}

void Log::indent()
{
    impl_->indent();
}

void Log::exdent()
{
    impl_->exdent();
}

void Log::disableFlush()
{
    impl_->disableFlush();
}

void Log::enableFlush()
{
    impl_->enableFlush();
}

void Log::forceFlush()
{
    impl_->pubsync();
}

void Log::disableHeader()
{
    impl_->disableHeader();
}

void Log::enableHeader()
{
    impl_->enableHeader();
}

void Log::setLogInfo( const char* file, const int line )
{
    impl_->setLogInfo( file, line );
}

void Log::setThreadName( const std::string& name )
{
    impl_->setThreadName( name );
}

const std::string& Log::getThreadName() const
{
    return impl_->getThreadName();
}

int Log::getLogLevel( const char* text )
{
    if( text )
    {
        const int num = atoi( text );
        if( num > 0 && num <= LOG_ALL )
            return num;

        for( uint32_t i = 0; i < LOG_TABLE_SIZE; ++i )
            if( _logTable[i].name == text )
                return _logTable[i].level;
    }

#ifdef NDEBUG
    return LOG_INFO;
#else
    return LOG_DEBUG;
#endif
}

std::string& Log::getLogLevelString()
{
    for( uint32_t i=0; i<LOG_TABLE_SIZE; ++i )
        if( _logTable[i].level == level )
                return _logTable[i].name;

    return _logTable[0].name;
}

unsigned getLogTopics()
{
    Log::level = Log::getLogLevel( getenv( "LB_LOG_LEVEL" ));
    const char *env = getenv( "LB_LOG_TOPICS" );

    if( env )
        return atoll(env);

    if( Log::level == LOG_ALL )
        return LOG_ANY;

#ifdef NDEBUG
    return 0;
#else
    return LOG_BUG;
#endif
}

Log& Log::instance()
{
    Log* log = _logInstance.get();
    if( !log )
    {
        log = new Log();
        _logInstance = log;
        static bool first = true;
        if( first && lunchbox::Log::level > LOG_INFO )
        {
            first = false;
            log->disableHeader();
            log->disableFlush();
            *log << std::setw( LENGTH_PID ) << std::right << "PID" << "."
                 << std::setw( LENGTH_THREAD ) << std::left << "Thread " << "|"
                 << std::setw( LENGTH_FILE+5 ) << " Filename:line " << "|"
                 << std::right << std::setw( LENGTH_TIME ) << " ms " << "|"
                 << " Message" << std::endl;
            log->enableFlush();
            log->enableHeader();
        }
    }

    return *log;
}

Log& Log::instance( const char* file, const int line )
{
    Log& log = instance();
    log.setLogInfo( file, line );
    return log;
}

void Log::exit()
{
    Log* log = _logInstance.get();
    _logInstance = 0;
    delete log;
}

void Log::reset()
{
    exit();

    delete _logFile;
    _logFile = 0;

#ifdef NDEBUG
    _logStream = &std::cout;
#else
    _logStream = &std::cerr;
#endif
}

void Log::setOutput( std::ostream& stream )
{
    _logStream = &stream;
    exit();
}

bool Log::setOutput( const std::string& file )
{
    std::ofstream* newLog = new std::ofstream( file.c_str( ));

    if( !newLog->is_open( ))
    {
        LBERROR << "Can't open log file " << file << ": " << sysError
                << std::endl;
        delete newLog;
        return false;
    }

    LBDEBUG << "Redirect log to " << file << std::endl;
    setOutput( *newLog );

    delete _logFile;
    _logFile = newLog;
    return true;
}

void Log::setClock( Clock* clock )
{
    if( clock )
        _clock = clock;
    else
        _clock = &_defaultClock;
}

const Clock& Log::getClock()
{
    return *_clock;
}

std::ostream& Log::getOutput()
{
    return *_logStream;
}

std::ostream& indent( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->indent();
    return os;
}
std::ostream& exdent( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->exdent();
    return os;
}

std::ostream& disableFlush( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->disableFlush();
    return os;
}
std::ostream& enableFlush( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->enableFlush();
    return os;
}
std::ostream& forceFlush( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->forceFlush();
    return os;
}

std::ostream& disableHeader( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->disableHeader();
    return os;
}
std::ostream& enableHeader( std::ostream& os )
{
    Log* log = dynamic_cast<Log*>(&os);
    if( log )
        log->enableHeader();
    return os;
}

}