Coverage Report

Created: 2026-08-31 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/appenderattachableimpl.cpp
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
#include <log4cxx/helpers/appenderattachableimpl.h>
18
#include <algorithm>
19
#include <mutex>
20
21
using namespace LOG4CXX_NS;
22
using namespace LOG4CXX_NS::helpers;
23
24
IMPLEMENT_LOG4CXX_OBJECT(AppenderAttachableImpl)
25
26
using AppenderListPtr = std::shared_ptr<const AppenderList>;
27
28
/** A vector of appender pointers. */
29
struct AppenderAttachableImpl::priv_data
30
{
31
private: // Attributes
32
#ifdef __cpp_lib_atomic_shared_ptr
33
  std::atomic<AppenderListPtr> pAppenderList;
34
#else // !defined(__cpp_lib_atomic_shared_ptr)
35
  AppenderListPtr    pAppenderList;
36
  mutable std::mutex m_mutex;
37
#endif // !defined(__cpp_lib_atomic_shared_ptr)
38
39
public: // ...structors
40
  priv_data(const AppenderList& newList = {})
41
1
    : pAppenderList{ std::make_shared<const AppenderList>(newList) }
42
1
  {}
43
44
public: // Attributes
45
  /**
46
  Serializes read-copy-update writers (addAppender, removeAppender, etc.)
47
  so a concurrent modification is not silently lost. Readers stay lock-free.
48
  */
49
  mutable std::mutex m_writeMutex;
50
51
public: // Accessors
52
  AppenderListPtr getAppenders() const
53
84.7k
  {
54
#ifdef __cpp_lib_atomic_shared_ptr
55
    return pAppenderList.load(std::memory_order_acquire);
56
#else // !defined(__cpp_lib_atomic_shared_ptr)
57
84.7k
    std::lock_guard<std::mutex> lock( m_mutex );
58
84.7k
    return pAppenderList;
59
84.7k
#endif // !defined(__cpp_lib_atomic_shared_ptr)
60
84.7k
  }
61
62
public: // Modifiers
63
  void setAppenders(const AppenderList& newList)
64
2
  {
65
#ifdef __cpp_lib_atomic_shared_ptr
66
    pAppenderList.store(std::make_shared<AppenderList>(newList), std::memory_order_release);
67
#else // !defined(__cpp_lib_atomic_shared_ptr)
68
2
    std::lock_guard<std::mutex> lock( m_mutex );
69
2
    pAppenderList = std::make_shared<const AppenderList>(newList);
70
2
#endif // !defined(__cpp_lib_atomic_shared_ptr)
71
2
  }
72
};
73
74
AppenderAttachableImpl::AppenderAttachableImpl()
75
1
  : m_priv(std::make_unique<priv_data>())
76
1
{
77
1
}
Unexecuted instantiation: log4cxx::helpers::AppenderAttachableImpl::AppenderAttachableImpl()
log4cxx::helpers::AppenderAttachableImpl::AppenderAttachableImpl()
Line
Count
Source
75
1
  : m_priv(std::make_unique<priv_data>())
76
1
{
77
1
}
78
79
#if LOG4CXX_ABI_VERSION <= 15
80
AppenderAttachableImpl::AppenderAttachableImpl(Pool& pool)
81
0
  : m_priv(std::make_unique<priv_data>())
82
0
{
83
0
}
Unexecuted instantiation: log4cxx::helpers::AppenderAttachableImpl::AppenderAttachableImpl(log4cxx::helpers::Pool&)
Unexecuted instantiation: log4cxx::helpers::AppenderAttachableImpl::AppenderAttachableImpl(log4cxx::helpers::Pool&)
84
#endif
85
AppenderAttachableImpl::~AppenderAttachableImpl()
86
1
{
87
1
}
88
89
90
void AppenderAttachableImpl::addAppender(const AppenderPtr newAppender)
91
0
{
92
0
  if (!newAppender)
93
0
    return;
94
0
  std::lock_guard<std::mutex> lock(m_priv->m_writeMutex);
95
0
  auto allAppenders = m_priv->getAppenders();
96
0
  if (allAppenders->end() == std::find(allAppenders->begin(), allAppenders->end(), newAppender))
97
0
  {
98
0
    auto newAppenders = *allAppenders;
99
0
    newAppenders.push_back(newAppender);
100
0
    m_priv->setAppenders(newAppenders);
101
0
  }
102
0
}
103
104
int AppenderAttachableImpl::appendLoopOnAppenders(const spi::LoggingEventPtr& event)
105
84.7k
{
106
84.7k
  int result = 0;
107
84.7k
  auto allAppenders = m_priv->getAppenders();
108
84.7k
  for (auto& appender : *allAppenders)
109
84.7k
  {
110
84.7k
    appender->doAppend(event);
111
84.7k
    ++result;
112
84.7k
  }
113
84.7k
  return result;
114
84.7k
}
115
#if LOG4CXX_ABI_VERSION <= 15
116
int AppenderAttachableImpl::appendLoopOnAppenders(const spi::LoggingEventPtr& event, helpers::Pool& p)
117
0
{
118
0
  return appendLoopOnAppenders(event);
119
0
}
120
#endif
121
122
AppenderList AppenderAttachableImpl::getAllAppenders() const
123
1
{
124
1
  return *m_priv->getAppenders();
125
1
}
126
127
AppenderPtr AppenderAttachableImpl::getAppender(const LogString& name) const
128
0
{
129
0
  AppenderPtr result;
130
0
  auto allAppenders = m_priv->getAppenders();
131
0
  for (auto& appender : *allAppenders)
132
0
  {
133
0
    if (name == appender->getName())
134
0
    {
135
0
      result = appender;
136
0
      break;
137
0
    }
138
0
  }
139
0
  return result;
140
0
}
141
142
bool AppenderAttachableImpl::isAttached(const AppenderPtr appender) const
143
0
{
144
0
  bool result = false;
145
0
  if (appender)
146
0
  {
147
0
    auto allAppenders = m_priv->getAppenders();
148
0
    result = allAppenders->end() != std::find(allAppenders->begin(), allAppenders->end(), appender);
149
0
  }
150
0
  return result;
151
0
}
152
153
void AppenderAttachableImpl::removeAllAppenders()
154
1
{
155
1
  std::lock_guard<std::mutex> lock(m_priv->m_writeMutex);
156
1
  auto allAppenders = m_priv->getAppenders();
157
1
  for (auto& appender : *allAppenders)
158
1
    appender->close();
159
1
  m_priv->setAppenders({});
160
1
}
161
162
void AppenderAttachableImpl::removeAppender(const AppenderPtr appender)
163
0
{
164
0
  if (appender)
165
0
  {
166
0
    std::lock_guard<std::mutex> lock(m_priv->m_writeMutex);
167
0
    auto newAppenders = *m_priv->getAppenders();
168
0
    auto pItem = std::find(newAppenders.begin(), newAppenders.end(), appender);
169
0
    if (newAppenders.end() != pItem)
170
0
    {
171
0
      newAppenders.erase(pItem);
172
0
      m_priv->setAppenders(newAppenders);
173
0
    }
174
0
  }
175
0
}
176
177
void AppenderAttachableImpl::removeAppender(const LogString& name)
178
0
{
179
0
  std::lock_guard<std::mutex> lock(m_priv->m_writeMutex);
180
0
  auto newAppenders = *m_priv->getAppenders();
181
0
  auto pItem = std::find_if(newAppenders.begin(), newAppenders.end()
182
0
    , [&name](const AppenderPtr& appender) -> bool
183
0
    {
184
0
      return name == appender->getName();
185
0
    });
186
0
  if (newAppenders.end() != pItem)
187
0
  {
188
0
    newAppenders.erase(pItem);
189
0
    m_priv->setAppenders(newAppenders);
190
0
  }
191
0
}
192
193
bool AppenderAttachableImpl::replaceAppender(const AppenderPtr& oldAppender, const AppenderPtr& newAppender)
194
0
{
195
0
  bool found = false;
196
0
  if (oldAppender && newAppender)
197
0
  {
198
0
    std::lock_guard<std::mutex> lock(m_priv->m_writeMutex);
199
0
    auto name = oldAppender->getName();
200
0
    auto newAppenders = *m_priv->getAppenders();
201
0
    auto pItem = std::find_if(newAppenders.begin(), newAppenders.end()
202
0
      , [&name](const AppenderPtr& appender) -> bool
203
0
      {
204
0
        return name == appender->getName();
205
0
      });
206
0
    if (newAppenders.end() != pItem)
207
0
    {
208
0
      *pItem = newAppender;
209
0
      m_priv->setAppenders(newAppenders);
210
0
      found = true;
211
0
    }
212
0
  }
213
0
  return found;
214
0
}
215
216
void AppenderAttachableImpl::replaceAppenders(const AppenderList& newList)
217
1
{
218
1
  std::lock_guard<std::mutex> lock(m_priv->m_writeMutex);
219
1
  auto allAppenders = m_priv->getAppenders();
220
1
  for (auto& a : *allAppenders)
221
0
    a->close();
222
1
  m_priv->setAppenders(newList);
223
1
}
224
225