Coverage Report

Created: 2026-03-31 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk/oflog/libsrc/asyncap.cc
Line
Count
Source
1
//  Copyright (C) 2009-2010, 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 "dcmtk/oflog/config.h"
25
#ifndef DCMTK_LOG4CPLUS_SINGLE_THREADED
26
27
#include "dcmtk/oflog/asyncap.h"
28
#include "dcmtk/oflog/spi/factory.h"
29
#include "dcmtk/oflog/helpers/loglog.h"
30
#include "dcmtk/oflog/helpers/property.h"
31
#include "dcmtk/oflog/thread/syncpub.h"
32
33
34
namespace dcmtk
35
{
36
namespace log4cplus
37
{
38
39
40
namespace
41
{
42
43
44
class QueueThread
45
    : public thread::AbstractThread
46
{
47
public:
48
    QueueThread (AsyncAppenderPtr const &, thread::QueuePtr const &);
49
50
    virtual void run();
51
52
private:
53
    AsyncAppenderPtr appenders;
54
    thread::QueuePtr queue;
55
};
56
57
58
QueueThread::QueueThread (AsyncAppenderPtr const & aai,
59
    thread::QueuePtr const & q)
60
0
    : appenders (aai)
61
0
    , queue (q)
62
0
{ }
63
64
65
void
66
QueueThread::run()
67
0
{
68
0
    typedef log4cplus::thread::Queue::queue_storage_type ev_buf_type;
69
0
    ev_buf_type ev_buf;
70
71
0
    while (true)
72
0
    {
73
0
        unsigned flags = queue->get_events (&ev_buf);
74
0
        if (flags & thread::Queue::EVENT)
75
0
        {
76
0
            ev_buf_type::const_iterator const ev_buf_end = ev_buf.end ();
77
0
            for (ev_buf_type::const_iterator it = ev_buf.begin ();
78
0
                it != ev_buf_end; ++it)
79
0
                appenders->appendLoopOnAppenders (*it);
80
0
        }
81
82
0
        if (((thread::Queue::EXIT | thread::Queue::DRAIN
83
0
                | thread::Queue::EVENT) & flags)
84
0
            == (thread::Queue::EXIT | thread::Queue::DRAIN
85
0
                | thread::Queue::EVENT))
86
0
            continue;
87
0
        else if (thread::Queue::EXIT & flags)
88
0
            break;
89
0
    }
90
0
}
91
92
93
} // namespace
94
95
96
AsyncAppender::AsyncAppender (SharedAppenderPtr const & app,
97
    unsigned queue_len)
98
0
    : queue_thread()
99
0
    , queue()
100
0
{
101
0
    addAppender (app);
102
0
    init_queue_thread (queue_len);
103
0
}
Unexecuted instantiation: dcmtk::log4cplus::AsyncAppender::AsyncAppender(dcmtk::log4cplus::helpers::SharedObjectPtr<dcmtk::log4cplus::Appender> const&, unsigned int)
Unexecuted instantiation: dcmtk::log4cplus::AsyncAppender::AsyncAppender(dcmtk::log4cplus::helpers::SharedObjectPtr<dcmtk::log4cplus::Appender> const&, unsigned int)
104
105
106
AsyncAppender::AsyncAppender (helpers::Properties const & props)
107
0
    : queue_thread()
108
0
    , queue()
109
0
{
110
0
    tstring const & appender_name =
111
0
        props.getProperty (DCMTK_LOG4CPLUS_TEXT ("Appender"));
112
0
    if (appender_name.empty ())
113
0
    {
114
0
        getErrorHandler ()->error (
115
0
            DCMTK_LOG4CPLUS_TEXT ("Unspecified appender for AsyncAppender."));
116
0
        return;
117
0
    }
118
119
0
    spi::AppenderFactoryRegistry & appender_registry
120
0
        = spi::getAppenderFactoryRegistry ();
121
0
    spi::AppenderFactory * factory = appender_registry.get (appender_name);
122
0
    if (! factory)
123
0
    {
124
0
        tstring const err (DCMTK_LOG4CPLUS_TEXT ("AsyncAppender::AsyncAppender()")
125
0
            DCMTK_LOG4CPLUS_TEXT (" - Cannot find AppenderFactory: "));
126
0
        helpers::getLogLog ().error (err + appender_name);
127
        // Add at least null appender so that we do not crash unexpectedly
128
        // elsewhere.
129
        // XXX: What about throwing an exception instead?
130
0
        factory = appender_registry.get (
131
0
            DCMTK_LOG4CPLUS_TEXT ("log4cplus::NullAppender"));
132
0
    }
133
134
0
    helpers::Properties appender_props = props.getPropertySubset (
135
0
        DCMTK_LOG4CPLUS_TEXT ("Appender."));
136
0
    addAppender (factory->createObject (appender_props));
137
138
0
    unsigned queue_len = 100;
139
0
    props.getUInt (queue_len, DCMTK_LOG4CPLUS_TEXT ("QueueLimit"));
140
141
0
    init_queue_thread (queue_len);
142
0
}
Unexecuted instantiation: dcmtk::log4cplus::AsyncAppender::AsyncAppender(dcmtk::log4cplus::helpers::Properties const&)
Unexecuted instantiation: dcmtk::log4cplus::AsyncAppender::AsyncAppender(dcmtk::log4cplus::helpers::Properties const&)
143
144
145
AsyncAppender::~AsyncAppender ()
146
0
{
147
0
    destructorImpl ();
148
0
}
149
150
151
void
152
AsyncAppender::init_queue_thread (unsigned queue_len)
153
0
{
154
0
    queue = new thread::Queue (queue_len);
155
0
    queue_thread = new QueueThread (AsyncAppenderPtr (this), queue);
156
0
    queue_thread->start ();
157
0
    helpers::getLogLog ().debug (DCMTK_LOG4CPLUS_TEXT("Queue thread started."));
158
0
}
159
160
161
void
162
AsyncAppender::close ()
163
0
{
164
0
    unsigned ret = queue->signal_exit ();
165
0
    if (ret & (thread::Queue::ERROR_BIT | thread::Queue::ERROR_AFTER))
166
0
        getErrorHandler ()->error (
167
0
            DCMTK_LOG4CPLUS_TEXT ("Error in AsyncAppender::close"));
168
0
    queue_thread->join ();
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
                DCMTK_LOG4CPLUS_TEXT ("Error in AsyncAppender::append,")
182
0
                DCMTK_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 = 0;
188
0
            queue = 0;
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
} // end namespace dcmtk
203
204
205
#endif // #ifndef DCMTK_LOG4CPLUS_SINGLE_THREADED