Coverage Report

Created: 2026-09-17 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/log4cplus/src/asyncappender.cxx
Line
Count
Source
1
//  Copyright (C) 2009-2017, Vaclav Haisman. All rights reserved.
2
//
3
//  Redistribution and use in source and binary forms, with or without modifica-
4
//  tion, are permitted provided that the following conditions are met:
5
//
6
//  1. Redistributions of  source code must  retain the above copyright  notice,
7
//     this list of conditions and the following disclaimer.
8
//
9
//  2. Redistributions in binary form must reproduce the above copyright notice,
10
//     this list of conditions and the following disclaimer in the documentation
11
//     and/or other materials provided with the distribution.
12
//
13
//  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
14
//  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
15
//  FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
16
//  APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
17
//  INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
18
//  DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
19
//  OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
20
//  ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
21
//  (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
22
//  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24
#include <log4cplus/config.hxx>
25
#ifndef LOG4CPLUS_SINGLE_THREADED
26
27
#include <log4cplus/asyncappender.h>
28
#include <log4cplus/spi/factory.h>
29
#include <log4cplus/helpers/loglog.h>
30
#include <log4cplus/helpers/property.h>
31
#include <log4cplus/thread/syncprims-pub-impl.h>
32
33
34
namespace log4cplus
35
{
36
37
38
namespace
39
{
40
41
42
class QueueThread
43
    : public thread::AbstractThread
44
{
45
public:
46
    QueueThread (AsyncAppenderPtr, thread::QueuePtr);
47
48
    void run() override;
49
50
private:
51
    AsyncAppenderPtr appenders;
52
    thread::QueuePtr queue;
53
};
54
55
56
QueueThread::QueueThread (AsyncAppenderPtr aai, thread::QueuePtr q)
57
0
    : appenders (std::move (aai))
58
0
    , queue (std::move (q))
59
0
{ }
60
61
62
void
63
QueueThread::run()
64
0
{
65
0
    typedef log4cplus::thread::Queue::queue_storage_type ev_buf_type;
66
0
    ev_buf_type ev_buf;
67
68
0
    while (true)
69
0
    {
70
0
        unsigned qflags = queue->get_events (&ev_buf);
71
0
        if (qflags & thread::Queue::EVENT)
72
0
        {
73
0
            ev_buf_type::const_iterator const ev_buf_end = ev_buf.end ();
74
0
            for (ev_buf_type::const_iterator it = ev_buf.begin ();
75
0
                it != ev_buf_end; ++it)
76
0
                appenders->appendLoopOnAppenders (*it);
77
0
        }
78
79
0
        if (((thread::Queue::EXIT | thread::Queue::DRAIN
80
0
                | thread::Queue::EVENT) & qflags)
81
0
            == (thread::Queue::EXIT | thread::Queue::DRAIN
82
0
                | thread::Queue::EVENT))
83
0
            continue;
84
0
        else if (thread::Queue::EXIT & qflags)
85
0
            break;
86
0
    }
87
0
}
88
89
90
} // namespace
91
92
93
AsyncAppender::AsyncAppender (SharedAppenderPtr const & app,
94
    unsigned queue_len)
95
0
{
96
0
    addAppender (app);
97
0
    init_queue_thread (queue_len);
98
0
}
Unexecuted instantiation: log4cplus::AsyncAppender::AsyncAppender(log4cplus::helpers::SharedObjectPtr<log4cplus::Appender> const&, unsigned int)
Unexecuted instantiation: log4cplus::AsyncAppender::AsyncAppender(log4cplus::helpers::SharedObjectPtr<log4cplus::Appender> const&, unsigned int)
99
100
101
AsyncAppender::AsyncAppender (helpers::Properties const & props)
102
0
    : Appender (props)
103
0
{
104
0
    tstring const & appender_name (
105
0
        props.getProperty (LOG4CPLUS_TEXT ("Appender")));
106
0
    if (appender_name.empty ())
107
0
    {
108
0
        getErrorHandler ()->error (
109
0
            LOG4CPLUS_TEXT ("Unspecified appender for AsyncAppender."));
110
0
        return;
111
0
    }
112
113
0
    spi::AppenderFactoryRegistry & appender_registry
114
0
        = spi::getAppenderFactoryRegistry ();
115
0
    spi::AppenderFactory * factory = appender_registry.get (appender_name);
116
0
    if (! factory)
117
0
    {
118
0
        helpers::getLogLog ().error (
119
0
            LOG4CPLUS_TEXT ("AsyncAppender::AsyncAppender()")
120
0
            LOG4CPLUS_TEXT (" - Cannot find AppenderFactory: ")
121
0
            + appender_name, true);
122
0
    }
123
124
0
    helpers::Properties appender_props = props.getPropertySubset (
125
0
        LOG4CPLUS_TEXT ("Appender."));
126
0
    addAppender (factory->createObject (appender_props));
127
128
0
    unsigned queue_len = 100;
129
0
    props.getUInt (queue_len, LOG4CPLUS_TEXT ("QueueLimit"));
130
131
0
    init_queue_thread (queue_len);
132
0
}
Unexecuted instantiation: log4cplus::AsyncAppender::AsyncAppender(log4cplus::helpers::Properties const&)
Unexecuted instantiation: log4cplus::AsyncAppender::AsyncAppender(log4cplus::helpers::Properties const&)
133
134
135
AsyncAppender::~AsyncAppender ()
136
0
{
137
0
    destructorImpl ();
138
0
}
139
140
141
void
142
AsyncAppender::init_queue_thread (unsigned queue_len)
143
0
{
144
0
    queue = new thread::Queue (queue_len);
145
0
    queue_thread = new QueueThread (AsyncAppenderPtr (this), queue);
146
0
    queue_thread->start ();
147
0
    helpers::getLogLog ().debug (LOG4CPLUS_TEXT("Queue thread started."));
148
0
}
149
150
151
void
152
AsyncAppender::close ()
153
0
{
154
0
    if (queue)
155
0
    {
156
0
        unsigned ret = queue->signal_exit ();
157
0
        if (ret & (thread::Queue::ERROR_BIT | thread::Queue::ERROR_AFTER))
158
0
            getErrorHandler ()->error (
159
0
                LOG4CPLUS_TEXT ("Error in AsyncAppender::close"));
160
0
    }
161
162
0
    if (queue_thread && queue_thread->isRunning ())
163
0
        queue_thread->join ();
164
165
0
    removeAllAppenders();
166
167
0
    queue_thread = nullptr;
168
0
    queue = nullptr;
169
0
}
170
171
172
void
173
AsyncAppender::append (spi::InternalLoggingEvent const & ev)
174
0
{
175
0
    if (queue_thread && queue_thread->isRunning ())
176
0
    {
177
0
        unsigned ret = queue->put_event (ev);
178
0
        if (ret & (thread::Queue::ERROR_BIT | thread::Queue::ERROR_AFTER))
179
0
        {
180
0
            getErrorHandler ()->error (
181
0
                LOG4CPLUS_TEXT ("Error in AsyncAppender::append,")
182
0
                LOG4CPLUS_TEXT (" event queue has been lost."));
183
            // Exit the queue consumer thread without draining
184
            // the events queue.
185
0
            queue->signal_exit (false);
186
0
            queue_thread->join ();
187
0
            queue_thread = nullptr;
188
0
            queue = nullptr;
189
0
            appendLoopOnAppenders (ev);
190
0
        }
191
0
    }
192
0
    else
193
0
    {
194
        // If the thread has died for any reason, fall back to synchronous
195
        // operation.
196
0
        appendLoopOnAppenders (ev);
197
0
    }
198
0
}
199
200
201
} // namespace log4cplus
202
203
204
#endif // #ifndef LOG4CPLUS_SINGLE_THREADED