idle_detect  0.8.3.0
Provides overall idle detection for a linux computer
util.h
1 /*
2  * Copyright (C) 2025 James C. Owens
3  * Portions Copyright (c) 2019 The Bitcoin Core developers
4  * Portions Copyright (c) 2025 The Gridcoin developers
5  *
6  * This code is licensed under the MIT license. See LICENSE.md in the repository.
7  */
8 
9 #ifndef UTIL_H
10 #define UTIL_H
11 
12 #include <atomic>
13 #include <map>
14 #include <mutex>
15 #include <optional>
16 #include <tinyformat.h>
17 #include <variant>
18 #include <vector>
19 #include <filesystem>
20 
21 namespace fs = std::filesystem;
22 
23 extern std::atomic<bool> g_debug;
24 extern std::atomic<bool> g_log_timestamps;
25 
29 template <typename T>
30 std::string ToString(const T& t)
31 {
32  std::ostringstream oss;
33  oss.imbue(std::locale::classic());
34  oss << t;
35  return oss.str();
36 }
37 
44 [[nodiscard]] std::vector<std::string> StringSplit(const std::string& s, const std::string& delim);
45 
52 [[nodiscard]] std::string TrimString(const std::string& str, const std::string& pattern = " \f\n\r\t\v");
53 
60 [[nodiscard]] std::string StripQuotes(const std::string& str);
61 
72 constexpr char ToLower(char c);
73 
83 std::string ToLower(const std::string& str);
84 
89 int64_t GetUnixEpochTime();
90 
96 std::string FormatISO8601DateTime(int64_t time);
97 
103 bool IsValidTimestamp(const int64_t& timestamp);
104 
105 template <typename... Args>
112 static inline std::string LogPrintStr(const char* fmt, const Args&... args)
113 {
114  std::string log_msg;
115 
116  // Conditionally add timestamp prefix based on g_log_timestamps flag.
117  if (g_log_timestamps.load(std::memory_order_relaxed)) { // Check the flag
118  log_msg = FormatISO8601DateTime(GetUnixEpochTime()) + " ";
119  }
120 
121  try {
122  log_msg += tfm::format(fmt, args...);
123  } catch (tinyformat::format_error& fmterr) {
124  /* Original format string will have newline so don't add one here */
125  log_msg += "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + fmt;
126  }
127 
128  log_msg += "\n";
129 
130  return log_msg;
131 }
132 
133 template <typename... Args>
139 void normal_log(const char* fmt, const Args&... args)
140 {
141  std::cout << LogPrintStr(fmt, args...);
142 }
143 
144 template <typename... Args>
150 void debug_log(const char* fmt, const Args&... args)
151 {
152  if (g_debug.load()) {
153  normal_log(fmt, args...);
154  }
155 }
156 
157 template <typename... Args>
163 void error_log(const char* fmt, const Args&... args)
164 {
165  std::string error_fmt = "ERROR: ";
166  error_fmt += fmt;
167 
168  std::cerr << LogPrintStr(error_fmt.c_str(), args...);
169 }
170 
171 [[nodiscard]] int ParseStringToInt(const std::string& str);
172 
173 [[nodiscard]] int64_t ParseStringtoInt64(const std::string& str);
174 
181 std::vector<fs::path> FindDirEntriesWithWildcard(const fs::path& directory, const std::string& wildcard);
182 
188 std::optional<std::string> GetEnvVariable(const std::string& var_name);
189 
193 class EventIdleDetectException : public std::exception
194 {
195 public:
196  EventIdleDetectException(const std::string& message) : m_message(message) {}
197  EventIdleDetectException(const char* message) : m_message(message) {}
198 
199  const char* what() const noexcept override {
200  return m_message.c_str();
201  }
202 
203 protected:
204  std::string m_message;
205 };
206 
209 {
210 public:
211  FileSystemException(const std::string& message, const std::filesystem::path& path)
212  : EventIdleDetectException(message + " Path: " + path.string()), m_path(path) {}
213 
214  const std::filesystem::path& path() const { return m_path; }
215 
216 private:
217  std::filesystem::path m_path;
218 };
219 
222 {
223 public:
224  ThreadException(const std::string& message) : EventIdleDetectException(message) {}
225 };
226 
227 typedef std::variant<bool, int, std::string, fs::path> config_variant;
228 
233 class Config
234 {
235 public:
239  Config();
240 
246  void ReadAndUpdateConfig(const fs::path& config_file);
247 
253  config_variant GetArg(const std::string& arg);
254 
255 protected:
263  std::string GetArgString(const std::string& arg, const std::string& default_value) const;
264 
269  std::multimap<std::string, config_variant> m_config;
270 
271 private:
276  virtual void ProcessArgs() = 0;
277 
278 
283  mutable std::mutex mtx_config;
284 
288  std::multimap<std::string, std::string> m_config_in;
289 
290 };
291 
302 {
303 public:
308  enum EventType { // Note that if this enum is expanded, EventTypeToString must also be updated.
309  UNKNOWN,
310  USER_ACTIVE,
311  USER_UNFORCE,
312  USER_FORCE_ACTIVE,
313  USER_FORCE_IDLE
314  };
315 
319  EventMessage();
320 
326  EventMessage(int64_t timestamp, EventType event_type);
327 
333  EventMessage(std::string timestamp_str, std::string event_type_str);
334 
339  std::string EventTypeToString();
340 
346  static std::string EventTypeToString(const EventType& event_type);
347 
352  bool IsValid();
353 
359  std::string ToString();
360 
361  int64_t m_timestamp;
362  EventType m_event_type;
363 
364 private:
370  EventType EventTypeStringToEnum(const std::string& event_type_str);
371 };
372 
373 
374 #endif // UTIL_H
std::string ToString()
Returns the string message format of the EventMessage object. This is meant to go on the pipe...
Definition: util.cpp:339
std::string GetArgString(const std::string &arg, const std::string &default_value) const
Private version of GetArg that operates on m_config_in and also selects the provided default value if...
Definition: util.cpp:261
std::multimap< std::string, config_variant > m_config
Holds the processed parameter-values, which are strongly typed and in a config_variant union...
Definition: util.h:269
EventType
The EventType enum defines event types for the EventMessage class. Currently there is only one event ...
Definition: util.h:308
File system related exceptions.
Definition: util.h:208
The Config class is a singleton that stores program config read from the config file, with applied defaults if the config file cannot be read, or a config parameter is not in the config file.
Definition: util.h:233
std::mutex mtx_config
This is the mutex member that provides lock control for the config object. This is used to ensure the...
Definition: util.h:283
virtual void ProcessArgs()=0
Private helper method used by ReadAndUpdateConfig. Note this is pure virtual. It must be implemented ...
Definition: tinyformat.h:167
The EventMessage class is a small class that encapsulates the "event message", which is a message sen...
Definition: util.h:301
Threading Related Exceptions.
Definition: util.h:221
bool IsValid()
Validates the EventMessage object.
Definition: util.cpp:334
std::multimap< std::string, std::string > m_config_in
Holds the raw parsed parameter-values from the config file.
Definition: util.h:288
void ReadAndUpdateConfig(const fs::path &config_file)
Reads and parses the config file provided by the argument and populates m_config_in, then calls private method ProcessArgs() to populate m_config.
Definition: util.cpp:200
std::string EventTypeToString()
Converts m_event_type member variable in the EventMessage object to a string.
Definition: util.cpp:304
EventMessage()
Constructs an "empty" EventMessage with timestamp of 0 and EventType of UNKNOWN.
Definition: util.cpp:272
The EventDetectException class is a customized exception handling class for the event_detect applicat...
Definition: util.h:193
config_variant GetArg(const std::string &arg)
Provides the config_variant type value of the config parameter (argument).
Definition: util.cpp:248
EventType EventTypeStringToEnum(const std::string &event_type_str)
This converts the event type string to the proper enum value. It is the converse of EventTypeToString...
Definition: util.cpp:277
Config()
Constructor.
Definition: util.cpp:197