mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-13 10:32:57 +01:00
This commit is contained in:
parent
562600aae3
commit
bf164a85a4
@ -72,6 +72,9 @@ public:
|
||||
Poco::UInt64 size() const;
|
||||
/// Returns file size
|
||||
|
||||
void flushToDisk();
|
||||
/// Forces buffered data to be written to the disk
|
||||
|
||||
protected:
|
||||
FileStreamBuf _buf;
|
||||
};
|
||||
|
@ -52,6 +52,9 @@ public:
|
||||
std::streampos seekpos(std::streampos pos, std::ios::openmode mode = std::ios::in | std::ios::out);
|
||||
/// Change to specified position, according to mode.
|
||||
|
||||
void flushToDisk();
|
||||
/// Forces buffered data to be written to the disk
|
||||
|
||||
NativeHandle nativeHandle() const;
|
||||
/// Returns native file descriptor handle
|
||||
|
||||
|
@ -51,6 +51,9 @@ public:
|
||||
std::streampos seekpos(std::streampos pos, std::ios::openmode mode = std::ios::in | std::ios::out);
|
||||
/// change to specified position, according to mode
|
||||
|
||||
void flushToDisk();
|
||||
/// Forces buffered data to be written to the disk
|
||||
|
||||
NativeHandle nativeHandle() const;
|
||||
/// Returns native file descriptor handle
|
||||
|
||||
|
@ -17,21 +17,14 @@
|
||||
#ifndef Foundation_LogFile_INCLUDED
|
||||
#define Foundation_LogFile_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "Poco/LogFile_WIN32U.h"
|
||||
#else
|
||||
#include "Poco/LogFile_STD.h"
|
||||
#endif
|
||||
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/FileStream.h"
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class Foundation_API LogFile: public LogFileImpl
|
||||
class Foundation_API LogFile
|
||||
/// This class is used by FileChannel to work
|
||||
/// with a log file.
|
||||
{
|
||||
@ -55,36 +48,15 @@ public:
|
||||
|
||||
const std::string& path() const;
|
||||
/// Returns the path given in the constructor.
|
||||
|
||||
private:
|
||||
std::string _path;
|
||||
mutable Poco::FileOutputStream _str;
|
||||
Timestamp _creationDate;
|
||||
UInt64 _size;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline void LogFile::write(const std::string& text, bool flush)
|
||||
{
|
||||
writeImpl(text, flush);
|
||||
}
|
||||
|
||||
|
||||
inline UInt64 LogFile::size() const
|
||||
{
|
||||
return sizeImpl();
|
||||
}
|
||||
|
||||
|
||||
inline Timestamp LogFile::creationDate() const
|
||||
{
|
||||
return creationDateImpl();
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& LogFile::path() const
|
||||
{
|
||||
return pathImpl();
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
|
@ -1,53 +0,0 @@
|
||||
//
|
||||
// LogFile_STD.h
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Logging
|
||||
// Module: LogFile
|
||||
//
|
||||
// Definition of the LogFileImpl class using iostreams.
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Foundation_LogFile_STD_INCLUDED
|
||||
#define Foundation_LogFile_STD_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/FileStream.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class Foundation_API LogFileImpl
|
||||
/// The implementation of LogFile for non-Windows platforms.
|
||||
/// The native filesystem APIs are used for
|
||||
/// total control over locking behavior.
|
||||
{
|
||||
public:
|
||||
LogFileImpl(const std::string& path);
|
||||
~LogFileImpl();
|
||||
void writeImpl(const std::string& text, bool flush);
|
||||
UInt64 sizeImpl() const;
|
||||
Timestamp creationDateImpl() const;
|
||||
const std::string& pathImpl() const;
|
||||
|
||||
private:
|
||||
std::string _path;
|
||||
mutable Poco::FileOutputStream _str;
|
||||
Timestamp _creationDate;
|
||||
UInt64 _size;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#endif // Foundation_LogFile_STD_INCLUDED
|
@ -1,54 +0,0 @@
|
||||
//
|
||||
// LogFile_WIN32U.h
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Logging
|
||||
// Module: LogFile
|
||||
//
|
||||
// Definition of the LogFileImpl class using the Windows file APIs.
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Foundation_LogFile_WIN32U_INCLUDED
|
||||
#define Foundation_LogFile_WIN32U_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/UnWindows.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class Foundation_API LogFileImpl
|
||||
/// The implementation of LogFile for Windows.
|
||||
/// The native filesystem APIs are used for
|
||||
/// total control over locking behavior.
|
||||
{
|
||||
public:
|
||||
LogFileImpl(const std::string& path);
|
||||
~LogFileImpl();
|
||||
void writeImpl(const std::string& text, bool flush);
|
||||
UInt64 sizeImpl() const;
|
||||
Timestamp creationDateImpl() const;
|
||||
const std::string& pathImpl() const;
|
||||
|
||||
private:
|
||||
void createFile();
|
||||
|
||||
std::string _path;
|
||||
HANDLE _hFile;
|
||||
Timestamp _creationDate;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#endif // Foundation_LogFile_WIN32U_INCLUDED
|
@ -42,7 +42,7 @@ const std::string FileChannel::PROP_ROTATEONOPEN = "rotateOnOpen";
|
||||
FileChannel::FileChannel():
|
||||
_times("utc"),
|
||||
_compress(false),
|
||||
_flush(true),
|
||||
_flush(false),
|
||||
_rotateOnOpen(false),
|
||||
_pFile(nullptr),
|
||||
_pRotateStrategy(new NullRotateStrategy()),
|
||||
@ -56,7 +56,7 @@ FileChannel::FileChannel(const std::string& path):
|
||||
_path(path),
|
||||
_times("utc"),
|
||||
_compress(false),
|
||||
_flush(true),
|
||||
_flush(false),
|
||||
_rotateOnOpen(false),
|
||||
_pFile(nullptr),
|
||||
_pRotateStrategy(new NullRotateStrategy()),
|
||||
|
@ -56,10 +56,18 @@ FileIOS::NativeHandle FileIOS::nativeHandle() const
|
||||
}
|
||||
|
||||
|
||||
Poco::UInt64 FileIOS::size() const {
|
||||
Poco::UInt64 FileIOS::size() const
|
||||
{
|
||||
return _buf.size();
|
||||
}
|
||||
|
||||
|
||||
void FileIOS::flushToDisk()
|
||||
{
|
||||
_buf.flushToDisk();
|
||||
}
|
||||
|
||||
|
||||
FileInputStream::FileInputStream():
|
||||
std::istream(&_buf)
|
||||
{
|
||||
|
@ -169,6 +169,17 @@ std::streampos FileStreamBuf::seekpos(std::streampos pos, std::ios::openmode mod
|
||||
}
|
||||
|
||||
|
||||
void FileStreamBuf::flushToDisk()
|
||||
{
|
||||
if (getMode() & std::ios::out)
|
||||
{
|
||||
sync();
|
||||
if (fsync(_fd) != 0)
|
||||
File::handleLastError(_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FileStreamBuf::NativeHandle FileStreamBuf::nativeHandle() const
|
||||
{
|
||||
return _fd;
|
||||
|
@ -199,6 +199,17 @@ std::streampos FileStreamBuf::seekpos(std::streampos pos, std::ios::openmode mod
|
||||
}
|
||||
|
||||
|
||||
void FileStreamBuf::flushToDisk()
|
||||
{
|
||||
if (getMode() & std::ios::out)
|
||||
{
|
||||
sync();
|
||||
if (FlushFileBuffers(_handle) == 0)
|
||||
File::handleLastError(_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FileStreamBuf::NativeHandle FileStreamBuf::nativeHandle() const
|
||||
{
|
||||
return _handle;
|
||||
|
@ -13,20 +13,34 @@
|
||||
|
||||
|
||||
#include "Poco/LogFile.h"
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "LogFile_WIN32U.cpp"
|
||||
#else
|
||||
#include "LogFile_STD.cpp"
|
||||
#endif
|
||||
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
LogFile::LogFile(const std::string& path): LogFileImpl(path)
|
||||
LogFile::LogFile(const std::string& path):
|
||||
_path(path),
|
||||
_str(_path, std::ios::app),
|
||||
_size(static_cast<UInt64>(_str.tellp()))
|
||||
{
|
||||
// There seems to be a strange "optimization" in the Windows NTFS
|
||||
// filesystem that causes it to reuse directory entries of deleted
|
||||
// files. Example:
|
||||
// 1. create a file named "test.dat"
|
||||
// note the file's creation date
|
||||
// 2. delete the file "test.dat"
|
||||
// 3. wait a few seconds
|
||||
// 4. create a file named "test.dat"
|
||||
// the new file will have the same creation
|
||||
// date as the old one.
|
||||
// We work around this bug by taking the file's
|
||||
// modification date as a reference when the
|
||||
// file is empty.
|
||||
if (_size == 0)
|
||||
_creationDate = File(path).getLastModified();
|
||||
else
|
||||
_creationDate = File(path).created();
|
||||
}
|
||||
|
||||
|
||||
@ -35,4 +49,63 @@ LogFile::~LogFile()
|
||||
}
|
||||
|
||||
|
||||
void LogFile::write(const std::string& text, bool flush)
|
||||
{
|
||||
std::streampos pos = _str.tellp();
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
// Replace \n with \r\n
|
||||
std::string logText;
|
||||
logText.reserve(text.size() + 16); // keep some reserve for \n -> \r\n
|
||||
char prevChar = 0;
|
||||
for (char c: text)
|
||||
{
|
||||
if (c == '\n' && prevChar != '\r')
|
||||
logText += POCO_DEFAULT_NEWLINE_CHARS;
|
||||
else
|
||||
logText += c;
|
||||
|
||||
prevChar = c;
|
||||
}
|
||||
_str << logText;
|
||||
#else
|
||||
_str << text;
|
||||
#endif
|
||||
|
||||
_str << POCO_DEFAULT_NEWLINE_CHARS;
|
||||
|
||||
if (flush)
|
||||
_str.flushToDisk();
|
||||
else
|
||||
_str.flush();
|
||||
|
||||
if (!_str.good())
|
||||
{
|
||||
_str.clear();
|
||||
_str.seekp(pos);
|
||||
throw WriteFileException(_path);
|
||||
}
|
||||
|
||||
_size = static_cast<UInt64>(_str.tellp());
|
||||
}
|
||||
|
||||
|
||||
UInt64 LogFile::size() const
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
|
||||
Timestamp LogFile::creationDate() const
|
||||
{
|
||||
return _creationDate;
|
||||
}
|
||||
|
||||
|
||||
const std::string& LogFile::path() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
@ -1,86 +0,0 @@
|
||||
//
|
||||
// LogFile_STD.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Logging
|
||||
// Module: LogFile
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/LogFile_STD.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
LogFileImpl::LogFileImpl(const std::string& path):
|
||||
_path(path),
|
||||
_str(_path, std::ios::app),
|
||||
_size(static_cast<UInt64>(_str.tellp()))
|
||||
{
|
||||
if (_size == 0)
|
||||
_creationDate = File(path).getLastModified();
|
||||
else
|
||||
_creationDate = File(path).created();
|
||||
}
|
||||
|
||||
|
||||
LogFileImpl::~LogFileImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void LogFileImpl::writeImpl(const std::string& text, bool flush)
|
||||
{
|
||||
std::streampos pos = _str.tellp();
|
||||
|
||||
_str << text << '\n';
|
||||
|
||||
// Flush the stream buffer to file to match the implementation on Windows
|
||||
_str.flush();
|
||||
|
||||
if (!_str.good())
|
||||
{
|
||||
_str.clear();
|
||||
_str.seekp(pos);
|
||||
throw WriteFileException(_path);
|
||||
}
|
||||
|
||||
if (flush)
|
||||
{
|
||||
// Sync the file to disk as it is done on Windows
|
||||
if (fsync(_str.nativeHandle()) != 0)
|
||||
throw WriteFileException(_path);
|
||||
}
|
||||
|
||||
_size = static_cast<UInt64>(_str.tellp());
|
||||
}
|
||||
|
||||
|
||||
UInt64 LogFileImpl::sizeImpl() const
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
|
||||
Timestamp LogFileImpl::creationDateImpl() const
|
||||
{
|
||||
return _creationDate;
|
||||
}
|
||||
|
||||
|
||||
const std::string& LogFileImpl::pathImpl() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
@ -1,127 +0,0 @@
|
||||
//
|
||||
// LogFile_WIN32U.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Logging
|
||||
// Module: LogFile
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/LogFile_WIN32U.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
|
||||
// TODO: LogStream shall use FileOutputStream for all implementations (see LogStream_STD)
|
||||
// TODO: Implement flushToDisk function in FileOutputStream.
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
LogFileImpl::LogFileImpl(const std::string& path): _path(path), _hFile(INVALID_HANDLE_VALUE)
|
||||
{
|
||||
File file(path);
|
||||
if (file.exists())
|
||||
{
|
||||
if (0 == sizeImpl())
|
||||
_creationDate = file.getLastModified();
|
||||
else
|
||||
_creationDate = file.created();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LogFileImpl::~LogFileImpl()
|
||||
{
|
||||
CloseHandle(_hFile);
|
||||
}
|
||||
|
||||
|
||||
void LogFileImpl::writeImpl(const std::string& text, bool flush)
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE == _hFile) createFile();
|
||||
|
||||
std::string logText;
|
||||
logText.reserve(text.size() + 16); // keep some reserve for \n -> \r\n and terminating \r\n
|
||||
for (char c: text)
|
||||
{
|
||||
if (c == '\n')
|
||||
logText += "\r\n";
|
||||
else
|
||||
logText += c;
|
||||
}
|
||||
logText += "\r\n";
|
||||
|
||||
DWORD bytesWritten;
|
||||
BOOL res = WriteFile(_hFile, logText.data(), static_cast<DWORD>(logText.size()), &bytesWritten, NULL);
|
||||
if (!res) throw WriteFileException(_path);
|
||||
if (flush)
|
||||
{
|
||||
res = FlushFileBuffers(_hFile);
|
||||
if (!res) throw WriteFileException(_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UInt64 LogFileImpl::sizeImpl() const
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE == _hFile)
|
||||
{
|
||||
File file(_path);
|
||||
if (file.exists()) return file.getSize();
|
||||
else return 0;
|
||||
}
|
||||
|
||||
LARGE_INTEGER li;
|
||||
li.HighPart = 0;
|
||||
li.LowPart = SetFilePointer(_hFile, 0, &li.HighPart, FILE_CURRENT);
|
||||
return li.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
Timestamp LogFileImpl::creationDateImpl() const
|
||||
{
|
||||
return _creationDate;
|
||||
}
|
||||
|
||||
|
||||
const std::string& LogFileImpl::pathImpl() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
|
||||
void LogFileImpl::createFile()
|
||||
{
|
||||
std::wstring upath;
|
||||
FileImpl::convertPath(_path, upath);
|
||||
|
||||
_hFile = CreateFileW(upath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (_hFile == INVALID_HANDLE_VALUE) throw OpenFileException(_path);
|
||||
SetFilePointer(_hFile, 0, 0, FILE_END);
|
||||
// There seems to be a strange "optimization" in the Windows NTFS
|
||||
// filesystem that causes it to reuse directory entries of deleted
|
||||
// files. Example:
|
||||
// 1. create a file named "test.dat"
|
||||
// note the file's creation date
|
||||
// 2. delete the file "test.dat"
|
||||
// 3. wait a few seconds
|
||||
// 4. create a file named "test.dat"
|
||||
// the new file will have the same creation
|
||||
// date as the old one.
|
||||
// We work around this bug by taking the file's
|
||||
// modification date as a reference when the
|
||||
// file is empty.
|
||||
if (sizeImpl() == 0)
|
||||
_creationDate = File(_path).getLastModified();
|
||||
else
|
||||
_creationDate = File(_path).created();
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
Loading…
Reference in New Issue
Block a user