Coverage Report

Created: 2025-07-01 06:08

/src/logging-log4cxx/src/main/cpp/filewatchdog.cpp
Line
Count
Source (jump to first uncovered line)
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
#define __STDC_CONSTANT_MACROS
18
#include <log4cxx/logstring.h>
19
#include <log4cxx/helpers/filewatchdog.h>
20
#include <log4cxx/helpers/loglog.h>
21
#include <log4cxx/helpers/transcoder.h>
22
#include <log4cxx/helpers/exception.h>
23
#include <log4cxx/helpers/threadutility.h>
24
#include <log4cxx/helpers/stringhelper.h>
25
#include <functional>
26
#include <chrono>
27
#include <thread>
28
#include <condition_variable>
29
30
using namespace LOG4CXX_NS;
31
using namespace LOG4CXX_NS::helpers;
32
33
long FileWatchdog::DEFAULT_DELAY = 60000;
34
35
struct FileWatchdog::FileWatchdogPrivate{
36
  FileWatchdogPrivate(const File& file1) :
37
0
    file(file1), delay(DEFAULT_DELAY), lastModif(0),
38
0
    warnedAlready(false),
39
0
    taskName{ LOG4CXX_STR("WatchDog_") + file1.getName() }
40
0
  { }
41
42
43
  /**
44
  The name of the file to observe  for changes.
45
  */
46
  File file;
47
48
  /**
49
  The delay to observe between every check.
50
  By default set DEFAULT_DELAY.*/
51
  long delay;
52
  log4cxx_time_t lastModif;
53
  bool warnedAlready;
54
  LogString taskName;
55
  ThreadUtility::ManagerWeakPtr taskManager;
56
};
57
58
FileWatchdog::FileWatchdog(const File& file1)
59
0
  : m_priv(std::make_unique<FileWatchdogPrivate>(file1))
60
0
{
61
0
}
62
63
FileWatchdog::~FileWatchdog()
64
0
{
65
0
  stop();
66
0
}
67
68
69
bool FileWatchdog::is_active()
70
0
{
71
0
  bool result = false;
72
0
  if (auto p = m_priv->taskManager.lock())
73
0
    result = p->value().hasPeriodicTask(m_priv->taskName);
74
0
  return result;
75
0
}
76
77
void FileWatchdog::stop()
78
0
{
79
0
  if (auto p = m_priv->taskManager.lock())
80
0
    p->value().removePeriodicTask(m_priv->taskName);
81
0
}
82
83
/**
84
Stop all tasks that periodically checks for a file change.
85
*/
86
void FileWatchdog::stopAll()
87
0
{
88
0
  ThreadUtility::instance()->removePeriodicTasksMatching(LOG4CXX_STR("WatchDog_"));
89
0
}
90
91
const File& FileWatchdog::file()
92
0
{
93
0
  return m_priv->file;
94
0
}
95
96
void FileWatchdog::checkAndConfigure()
97
0
{
98
0
  if (LogLog::isDebugEnabled())
99
0
  {
100
0
    LogString msg(LOG4CXX_STR("Checking ["));
101
0
    msg += m_priv->file.getPath();
102
0
    msg += LOG4CXX_STR("]");
103
0
    LogLog::debug(msg);
104
0
  }
105
0
  Pool pool1;
106
107
0
  if (!m_priv->file.exists(pool1))
108
0
  {
109
0
    if (!m_priv->warnedAlready)
110
0
    {
111
0
      LogLog::warn(LOG4CXX_STR("[")
112
0
        + m_priv->file.getPath()
113
0
        + LOG4CXX_STR("] does not exist."));
114
0
      m_priv->warnedAlready = true;
115
0
    }
116
0
  }
117
0
  else
118
0
  {
119
0
    auto thisMod = m_priv->file.lastModified(pool1);
120
121
0
    if (thisMod > m_priv->lastModif)
122
0
    {
123
0
      m_priv->lastModif = thisMod;
124
0
      doOnChange();
125
0
      m_priv->warnedAlready = false;
126
0
    }
127
0
  }
128
0
}
129
130
void FileWatchdog::start()
131
0
{
132
0
  auto taskManager = ThreadUtility::instancePtr();
133
0
  checkAndConfigure();
134
0
  if (!taskManager->value().hasPeriodicTask(m_priv->taskName))
135
0
  {
136
0
    if (LogLog::isDebugEnabled())
137
0
    {
138
0
      Pool p;
139
0
      LogString msg(LOG4CXX_STR("Checking ["));
140
0
      msg += m_priv->file.getPath();
141
0
      msg += LOG4CXX_STR("] at ");
142
0
      StringHelper::toString((int)m_priv->delay, p, msg);
143
0
      msg += LOG4CXX_STR(" ms interval");
144
0
      LogLog::debug(msg);
145
0
    }
146
0
    taskManager->value().addPeriodicTask(m_priv->taskName
147
0
      , std::bind(&FileWatchdog::checkAndConfigure, this)
148
0
      , std::chrono::milliseconds(m_priv->delay)
149
0
      );
150
0
    m_priv->taskManager = taskManager;
151
0
  }
152
0
}
153
154
0
void FileWatchdog::setDelay(long delay1){
155
0
  m_priv->delay = delay1;
156
0
  auto p = m_priv->taskManager.lock();
157
0
  if (p && p->value().hasPeriodicTask(m_priv->taskName))
158
0
  {
159
0
    p->value().removePeriodicTask(m_priv->taskName);
160
0
    p->value().addPeriodicTask(m_priv->taskName
161
0
      , std::bind(&FileWatchdog::checkAndConfigure, this)
162
0
      , std::chrono::milliseconds(m_priv->delay)
163
0
      );
164
0
  }
165
0
}