• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            開源日志系統(tǒng)log4cplus(七)

             

            經(jīng)過短暫的熟悉過程,log4cplus已經(jīng)被成功應(yīng)用到了我的項(xiàng)目中去了,效果還不錯,:)除了上文提及的
            功能之外,下面將介紹log4cplus提供的線程和套接字的使用情況。

            ### NDC ###
            首先我們先了解一下log4cplus中嵌入診斷上下文(Nested Diagnostic Context),即NDC。對log系統(tǒng)而言,
            當(dāng)輸入源可能不止一個,而只有一個輸出時,往往需要分辯所要輸出消息的來源,比如服務(wù)器處理來自不同
            客戶端的消息時就需要作此判斷,NDC可以為交錯顯示的信息打上一個標(biāo)記(stamp), 使得辨認(rèn)工作看起來
            比較容易些,呵呵。這個標(biāo)記是線程特有的,利用了線程局部存儲機(jī)制,稱為線程私有數(shù)據(jù)(Thread-specific
             Data,或TSD)。 看了一下源代碼,相關(guān)定義如下,包括定義、初始化、獲取、設(shè)置和清除操作:
            linux pthread
            #   define LOG4CPLUS_THREAD_LOCAL_TYPE pthread_key_t*
            #   define LOG4CPLUS_THREAD_LOCAL_INIT ::log4cplus::thread::createPthreadKey()
            #   define LOG4CPLUS_GET_THREAD_LOCAL_VALUE( key ) pthread_getspecific(
            *key)
            #   define LOG4CPLUS_SET_THREAD_LOCAL_VALUE( key, value ) pthread_setspecific(
            *key, value)
            #   define LOG4CPLUS_THREAD_LOCAL_CLEANUP( key ) pthread_key_delete(
            *key)

            win32
            #   define LOG4CPLUS_THREAD_LOCAL_TYPE DWORD
            #   define LOG4CPLUS_THREAD_LOCAL_INIT TlsAlloc()
            #   define LOG4CPLUS_GET_THREAD_LOCAL_VALUE( key ) TlsGetValue(key)
            #   define LOG4CPLUS_SET_THREAD_LOCAL_VALUE( key, value ) \       TlsSetValue(key, static_cast(value))
            #   define LOG4CPLUS_THREAD_LOCAL_CLEANUP( key ) TlsFree(key)
            				
            使用起來比較簡單,在某個線程中:
                NDC& ndc = log4cplus::getNDC();
                ndc.push(
            "ur ndc string");
                LOG4CPLUS_DEBUG(logger, 
            "this is a NDC test");
                 
                ndc.pop();
                    
                LOG4CPLUS_DEBUG(logger, 
            "There should be no NDC");
                ndc.remove();


               
            當(dāng)設(shè)定輸出格式(Layout)為TTCCLayout時,輸出如下:
            10-21-04 21:32:58, [3392] DEBUG test  - this is a NDC test
            10-21-04 21:32:58, [3392] DEBUG test <> - There should be no NDC...
            也可以在自定義的輸出格式中使用NDC(用%x) ,比如:
                 
              std::
            string pattern = "NDC:[%x]  - %m %n";
              std::auto_ptr _layout(
            new PatternLayout(pattern));
                 
             LOG4CPLUS_DEBUG(_logger, 
            "This is the FIRST log message")
              NDC
            & ndc = log4cplus::getNDC();
              ndc.push(
            "ur ndc string"); 
              LOG4CPLUS_WARN(_logger, 
            "This is the SECOND log message")
              ndc.pop();
             ndc.remove(); 
                

               
            輸出如下:
            NDC:[]  - This is the FIRST log message...
            NDC:[ur ndc string]  - This is the SECOND log message...
            				
            另外一種更簡單的使用方法是在線程中直接用NDCContextCreator:
                NDCContextCreator _first_ndc("ur ndc string");
                LOG4CPLUS_DEBUG(logger, 
            "this is a NDC test")

               
            不必顯式地調(diào)用push/pop了,而且當(dāng)出現(xiàn)異常時,能夠確保push與pop的調(diào)用是匹配的。
                
            ### 線程 ###
            線程是log4cplus中的副產(chǎn)品, 而且僅作了最基本的實(shí)現(xiàn),使用起來也異常簡單,只要且必須要
            在派生類中重載run函數(shù)即可:
            class TestThread : public AbstractThread
            {
            public:
                
            virtual void run();
            }
            ;
                            
            void TestThread::run()

               
            /* do sth. */ 
                
            }

            log4cplus的線程沒有考慮同步、死鎖,有互斥,實(shí)現(xiàn)線程切換的小函數(shù)挺別致的:
            void log4cplus::thread::yield()
            {
            #if defined(LOG4CPLUS_USE_PTHREADS)
                ::sched_yield();
            #elif defined(LOG4CPLUS_USE_WIN32_THREADS)
                ::Sleep(
            0);
            #endif
            }
            				
            ### 套接字 ###
            套接字也是log4cplus中的副產(chǎn)品,在namespace log4cplus::helpers中,實(shí)現(xiàn)了C/S方式的日志記錄。
            1. 客戶端程序需要做的工作:
            /* 定義一個SocketAppender類型的掛接器 */SharedAppenderPtr _append(new SocketAppender(host, 8888"ServerName"));
            /* 把_append加入到logger中 */Logger::getRoot().addAppender(_append);
            /*  SocketAppender類型不需要Layout, 直接調(diào)用宏就可以將信息發(fā)往loggerServer了 */LOG4CPLUS_INFO(Logger::getRoot(), "This is a test: ")

            【注】 這里對宏的調(diào)用其實(shí)是調(diào)用了SocketAppender::append,里面有一個數(shù)據(jù)傳輸約定,即先發(fā)送
            一個后續(xù)數(shù)據(jù)的總長度,然后再發(fā)送實(shí)際的數(shù)據(jù):
                 
                SocketBuffer buffer 
            = convertToBuffer(event, serverName);
                SocketBuffer msgBuffer(LOG4CPLUS_MAX_MESSAGE_SIZE);
                msgBuffer.appendSize_t(buffer.getSize());
                msgBuffer.appendBuffer(buffer);        
            				
            2. 服務(wù)器端程序需要做的工作:
            /* 定義一個ServerSocket */ServerSocket serverSocket(port);
             
            /* 調(diào)用accept函數(shù)創(chuàng)建一個新的socket與客戶端連接 */Socket sock = serverSocket.accept();
            				
            此后即可用該sock進(jìn)行數(shù)據(jù)read/write了,形如:
            SocketBuffer msgSizeBuffer(sizeof(unsigned int));
            if(!clientsock.read(msgSizeBuffer))
            {
                
            return;
            }

            unsigned 
            int msgSize = msgSizeBuffer.readInt();
            SocketBuffer buffer(msgSize);
            if(!clientsock.read(buffer))
            {
                
            return;
            }

            為了將讀到的數(shù)據(jù)正常顯示出來,需要將SocketBuffer存放的內(nèi)容轉(zhuǎn)換成InternalLoggingEvent格式:
            spi::InternalLoggingEvent event = readFromBuffer(buffer);
            然后輸出:
            Logger logger = Logger::getInstance(event.getLoggerName());
            logger.callAppenders(
            event);
            				
            【注】 read/write是按照阻塞方式實(shí)現(xiàn)的,意味著對其調(diào)用直到滿足了所接收或發(fā)送的個數(shù)才返回。

            posted on 2006-08-26 04:51 楊粼波 閱讀(5400) 評論(3)  編輯 收藏 引用 所屬分類: Windows編程 、Linux編程

            評論

            # re: 開源日志系統(tǒng)log4cplus(七)[未登錄] 2008-04-18 12:17 cppexplore

            精彩!多多發(fā)點(diǎn)這種造福大眾的文章啊!  回復(fù)  更多評論   

            # re: 開源日志系統(tǒng)log4cplus(七) 2008-07-23 14:54 齊全愛

            很好,多謝?。?!支持你?。。?nbsp; 回復(fù)  更多評論   

            # re: 開源日志系統(tǒng)log4cplus(七) 2010-05-13 17:22 yacper

            perfect  回復(fù)  更多評論   

            国产激情久久久久影院老熟女免费 | 久久精品国产清高在天天线| 久久这里有精品视频| 2021精品国产综合久久| 久久九九兔免费精品6| 亚洲精品第一综合99久久| 蜜臀久久99精品久久久久久| 国产视频久久| 久久国产热这里只有精品| 93精91精品国产综合久久香蕉 | 国产精品久久久久久久久久免费| 久久精品水蜜桃av综合天堂| 漂亮人妻被黑人久久精品| 久久久精品2019免费观看| 国产麻豆精品久久一二三| 久久99国产精品二区不卡| 中文字幕久久欲求不满| 久久er国产精品免费观看8| 久久综合色区| 久久亚洲AV无码精品色午夜麻豆| 狠狠精品久久久无码中文字幕| 99精品久久精品一区二区| 久久久久久亚洲Av无码精品专口| 欧美牲交A欧牲交aⅴ久久| 97久久精品午夜一区二区| 中文字幕成人精品久久不卡| 久久亚洲欧洲国产综合| 国产欧美久久久精品影院| 人妻久久久一区二区三区| 久久国产精品-久久精品| 久久久久亚洲AV无码去区首| 久久伊人五月丁香狠狠色| 久久w5ww成w人免费| 九九久久99综合一区二区| 亚洲精品国精品久久99热| 少妇高潮惨叫久久久久久| 亚洲国产精品热久久| 日批日出水久久亚洲精品tv| 久久人爽人人爽人人片AV| 国产三级精品久久| 久久99精品久久久久久hb无码|