log stream implementation issue
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2

Thread: log stream implementation issue

Hybrid View

  1. #1
    Join Date
    Aug 2010
    Posts
    1

    log stream implementation issue

    dear friends,

    I am developing a simple log stream class by deriving and over-riding ostream and streambuf classes. The purpose of this class is to provide insertion operator (<<) kind of syntax for logging messages. In addition, this class inserts a date string automatically to every new line.

    The code of this class is given here:

    Code:
    #include <ostream>
    #include <fstream>
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    class LogBuf : public filebuf {
     
    public:
        LogBuf(const char* file) : bNewLine_(true), writeP_(0) {
            open(file, ios::out);
        }   
    
        int sync() {
            cout << "syncing..." << endl;
            long len = strlen(pbase());
            if (len > 0) processDate('\n');
            int iRet = filebuf::sync();
    
            reset();
            return iRet;
        }   
    
        void processDate(int ch) {
    
            char* bufs;
            time_t t;
            struct tm* timeinfo;
            time(&t);
            timeinfo = localtime(&t);
            bufs = pbase();
    
            cout << "date processing..." << endl;
            size_t contentLen = strlen(bufs) + 1;
    
            for (size_t i=0; i<contentLen;  ++i) {
                if (bNewLine_) {
                    writeP_ += strftime(buf_+writeP_, (sizeof(buf_)-writeP_), "[%Y%m%d-%H%M%S] ", timeinfo);
                    bNewLine_ = !bNewLine_;
                }
                if (bufs[i] == '\n') bNewLine_ = true;
                buf_[writeP_++] = bufs[i];
            }
    
            setp(buf_, buf_+writeP_);
            pbump(writeP_);
        }
    
        ~LogBuf() {
            cout << "LogBuf::destructor at work..." << endl;
            sync();
        }
    
    private:
        char buf_[1024];
        bool bNewLine_;
        size_t writeP_;
    
        void reset() {
            memset(buf_, 0x00, sizeof(buf_));
            writeP_ =0;
        }
    };
    
    
    class DebugStream : private LogBuf, public ostream {
    public:
        DebugStream(const char* file):LogBuf(file), ostream (this) { }
    };

    - The above program has two classes DebugStream and LogBuf.
    - LogBuf's processDate() method scans the output string and inserts a date string after every new line character.

    and, the test code is like this.

    Code:
    #include "Rsdpdebug.hpp"
    
    int main(int argc, char** argv) {
    
        DebugStream ds ("log.log");
        ds << "Hello first logger world!" << "\n" ;
        ds << "Hello second logger world!" << '\n';
        ds << "Hello third logger world!" ;
        ds << "Hello fourth logger world!" << endl;
    }

    The problem is that
    - If in the test code, no "endl" is given, then the 'sync()' never gets called, and so the method processDate() is never called.
    - On the other hand, if an endl is given, the output is repeated multiple times like this below...

    20100809-072039] Hello first logger world!
    [20100809-072039] Hello second logger world!
    [20100809-072039] Hello third logger world!Hello fourth logger world!
    [20100809-072039] Hello first logger world!
    [20100809-072039] Hello second logger world!
    [20100809-072039] Hello third logger world!Hello fourth logger world!
    Can anyone suggest what is going wrong in here...

    thanks in advance,
    RV

  2. #2
    Join Date
    Jul 2009
    Location
    Gothenburg
    Posts
    12

    Re: log stream implementation issue

    Four things:

    1. You may not assume that the buffers are null-terminated, don't use strlen()

    2. When calling setp() you are replacing the previous buffer with your own.
    This means that when syncing a second time you are reading and writing from the same buffer. Restore the old buffer after syncing.

    3. You need a more thorough check for buffer overflow, make sure you're not writing past your buffer.

    4. You may need a larger buffer if you're not going to sync often, otherwise the output will be truncated.
    [Edit] You should sync after every message though, because the time written is the time of syncing, not the time the message was added to the log.

    Anyway, this code works for me at least:
    Code:
        int sync() {
            cout << "syncing..." << endl;
            char *old_base = pbase ();
            char *old_end = epptr ();
            long len = pptr () - pbase();
            if (len > 0) processDate('\n');
            int iRet = filebuf::sync();
            setp (old_base, old_end);
    
            reset();
            return iRet;
        }   
    
        void processDate(int ch) {
    
            char* bufs;
            time_t t;
            struct tm* timeinfo;
            time(&t);
            timeinfo = localtime(&t);
            
            cout << "date processing..." << endl;
    
            for (bufs = pbase(); bufs < pptr () && writeP_ < sizeof(buf_);  ++bufs) {
                if (bNewLine_) {
                    writeP_ += strftime(buf_+writeP_, (sizeof(buf_)-writeP_), "[&#37;Y%m%d-%H%M%S] ", timeinfo);
                    bNewLine_ = false;
                }
                if (*bufs == '\n') bNewLine_ = true;
                buf_[writeP_++] = *bufs;
            }
    
            setp(buf_, buf_+writeP_);
            pbump(writeP_);
        }
    Last edited by spacewarp; August 9th, 2010 at 09:37 AM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center