source: trunk/GDE/SINA/builddir/include/spdlog/details/file_helper.h

Last change on this file was 19170, checked in by westram, 2 years ago
  • sina source
    • unpack + remove tarball
    • no longer ignore sina builddir.
File size: 3.8 KB
Line 
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 sinks.
9// When failing to open a file, retry several times(5) with a delay interval(10 ms).
10// Throw spdlog_ex exception on errors.
11
12#include "spdlog/details/log_msg.h"
13#include "spdlog/details/os.h"
14
15#include <cerrno>
16#include <chrono>
17#include <cstdio>
18#include <string>
19#include <thread>
20#include <tuple>
21
22namespace spdlog {
23namespace details {
24
25class file_helper
26{
27
28public:
29    const int open_tries = 5;
30    const int open_interval = 10;
31
32    explicit file_helper() = default;
33
34    file_helper(const file_helper &) = delete;
35    file_helper &operator=(const file_helper &) = delete;
36
37    ~file_helper()
38    {
39        close();
40    }
41
42    void open(const filename_t &fname, bool truncate = false)
43    {
44        close();
45        auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
46        _filename = fname;
47        for (int tries = 0; tries < open_tries; ++tries)
48        {
49            if (!os::fopen_s(&fd_, fname, mode))
50            {
51                return;
52            }
53
54            details::os::sleep_for_millis(open_interval);
55        }
56
57        throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno);
58    }
59
60    void reopen(bool truncate)
61    {
62        if (_filename.empty())
63        {
64            throw spdlog_ex("Failed re opening file - was not opened before");
65        }
66        open(_filename, truncate);
67    }
68
69    void flush()
70    {
71        std::fflush(fd_);
72    }
73
74    void close()
75    {
76        if (fd_ != nullptr)
77        {
78            std::fclose(fd_);
79            fd_ = nullptr;
80        }
81    }
82
83    void write(const fmt::memory_buffer &buf)
84    {
85        size_t msg_size = buf.size();
86        auto data = buf.data();
87        if (std::fwrite(data, 1, msg_size, fd_) != msg_size)
88        {
89            throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno);
90        }
91    }
92
93    size_t size() const
94    {
95        if (fd_ == nullptr)
96        {
97            throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename));
98        }
99        return os::filesize(fd_);
100    }
101
102    const filename_t &filename() const
103    {
104        return _filename;
105    }
106
107    static bool file_exists(const filename_t &fname)
108    {
109        return os::file_exists(fname);
110    }
111
112    //
113    // return file path and its extension:
114    //
115    // "mylog.txt" => ("mylog", ".txt")
116    // "mylog" => ("mylog", "")
117    // "mylog." => ("mylog.", "")
118    // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
119    //
120    // the starting dot in filenames is ignored (hidden files):
121    //
122    // ".mylog" => (".mylog". "")
123    // "my_folder/.mylog" => ("my_folder/.mylog", "")
124    // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
125    static std::tuple<filename_t, filename_t> split_by_extension(const spdlog::filename_t &fname)
126    {
127        auto ext_index = fname.rfind('.');
128
129        // no valid extension found - return whole path and empty string as
130        // extension
131        if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1)
132        {
133            return std::make_tuple(fname, spdlog::filename_t());
134        }
135
136        // treat casese like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
137        auto folder_index = fname.rfind(details::os::folder_sep);
138        if (folder_index != filename_t::npos && folder_index >= ext_index - 1)
139        {
140            return std::make_tuple(fname, spdlog::filename_t());
141        }
142
143        // finally - return a valid base and extension tuple
144        return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
145    }
146
147private:
148    std::FILE *fd_{nullptr};
149    filename_t _filename;
150};
151} // namespace details
152} // namespace spdlog
Note: See TracBrowser for help on using the repository browser.