xref: /aosp_15_r20/external/gmmlib/Source/GmmLib/Utility/GmmLog/spdlog/details/file_helper.h (revision 35ffd701415c9e32e53136d61a677a8d0a8fc4a5)
1 //
2 // Copyright(c) 2015 Gabi Melman.
3 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
4 //
5 
6 #pragma once
7 
8 // Helper class for file sink
9 // When failing to open a file, retry several times(5) with small delay between the tries(10 ms)
10 // Can be set to auto flush on every line
11 // Throw spdlog_ex exception on errors
12 
13 #include <spdlog/details/os.h>
14 #include <spdlog/details/log_msg.h>
15 
16 #include <chrono>
17 #include <cstdio>
18 #include <string>
19 #include <thread>
20 #include <cerrno>
21 
22 namespace spdlog
23 {
24 namespace details
25 {
26 
27 class file_helper
28 {
29 
30 public:
31     const int open_tries = 5;
32     const int open_interval = 10;
33 
file_helper()34     explicit file_helper() :
35         _fd(nullptr)
36     {}
37 
38     file_helper(const file_helper&) = delete;
39     file_helper& operator=(const file_helper&) = delete;
40 
~file_helper()41     ~file_helper()
42     {
43         close();
44     }
45 
46 
47     void open(const filename_t& fname, bool truncate = false)
48     {
49 
50         close();
51         auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
52         _filename = fname;
53         for (int tries = 0; tries < open_tries; ++tries)
54         {
55             if (!os::fopen_s(&_fd, fname, mode))
56                 return;
57 
58             std::this_thread::sleep_for(std::chrono::milliseconds(open_interval));
59         }
60 
61         throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno);
62     }
63 
reopen(bool truncate)64     void reopen(bool truncate)
65     {
66         if (_filename.empty())
67             throw spdlog_ex("Failed re opening file - was not opened before");
68         open(_filename, truncate);
69 
70     }
71 
flush()72     void flush()
73     {
74         std::fflush(_fd);
75     }
76 
close()77     void close()
78     {
79         if (_fd)
80         {
81             std::fclose(_fd);
82             _fd = nullptr;
83         }
84     }
85 
write(const log_msg & msg)86     void write(const log_msg& msg)
87     {
88 
89         size_t msg_size = msg.formatted.size();
90         auto data = msg.formatted.data();
91         if (std::fwrite(data, 1, msg_size, _fd) != msg_size)
92             throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno);
93     }
94 
size()95     size_t size()
96     {
97         if (!_fd)
98             throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename));
99         return os::filesize(_fd);
100     }
101 
filename()102     const filename_t& filename() const
103     {
104         return _filename;
105     }
106 
file_exists(const filename_t & name)107     static bool file_exists(const filename_t& name)
108     {
109 
110         return os::file_exists(name);
111     }
112 
113 private:
114     FILE* _fd;
115     filename_t _filename;
116 };
117 }
118 }
119