mirror of
				https://github.com/pocoproject/poco.git
				synced 2025-10-27 11:06:50 +01:00 
			
		
		
		
	This commit is contained in:
		| @@ -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 | ||||
		Reference in New Issue
	
	Block a user
	 Matej Kenda
					Matej Kenda