mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-30 19:23:03 +01:00
75e2751c50
Remove some debugging code.
209 lines
4.9 KiB
C++
209 lines
4.9 KiB
C++
/*
|
|
* PROGRAM: SQL Trace plugin
|
|
* MODULE: PluginLogWriter.cpp
|
|
* DESCRIPTION: Plugin log writer implementation
|
|
*
|
|
* The contents of this file are subject to the Initial
|
|
* Developer's Public License Version 1.0 (the "License");
|
|
* you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
|
*
|
|
* Software distributed under the License is distributed AS IS,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing rights
|
|
* and limitations under the License.
|
|
*
|
|
* The Original Code was created by Khorsun Vladyslav
|
|
* for the Firebird Open Source RDBMS project.
|
|
*
|
|
* Copyright (c) 2009 Khorsun Vladyslav <hvlad@users.sourceforge.net>
|
|
* and all contributors signed below.
|
|
*
|
|
* All Rights Reserved.
|
|
* Contributor(s): ______________________________________.
|
|
*
|
|
*/
|
|
|
|
#include "PluginLogWriter.h"
|
|
|
|
using namespace Firebird;
|
|
|
|
|
|
PluginLogWriter::PluginLogWriter(const char* fileName, size_t maxSize) :
|
|
m_fileName(*getDefaultMemoryPool()),
|
|
m_fileHandle(-1),
|
|
m_maxSize(maxSize)
|
|
{
|
|
m_fileName = fileName;
|
|
|
|
#ifdef WIN_NT
|
|
PathName mutexName("fb_mutex_");
|
|
mutexName.append(m_fileName);
|
|
|
|
checkMutex("init", ISC_mutex_init(&m_mutex, mutexName.c_str()));
|
|
#endif
|
|
}
|
|
|
|
PluginLogWriter::~PluginLogWriter()
|
|
{
|
|
if (m_fileHandle != -1)
|
|
::close(m_fileHandle);
|
|
|
|
#ifdef WIN_NT
|
|
ISC_mutex_fini(&m_mutex);
|
|
#endif
|
|
}
|
|
|
|
SINT64 PluginLogWriter::seekToEnd()
|
|
{
|
|
#ifdef WIN_NT
|
|
SINT64 nFileLen = _lseeki64(m_fileHandle, 0, SEEK_END);
|
|
#else
|
|
off_t nFileLen = lseek(m_fileHandle, 0, SEEK_END);
|
|
#endif
|
|
|
|
if (nFileLen < 0)
|
|
checkErrno("lseek");
|
|
|
|
return nFileLen;
|
|
}
|
|
|
|
void PluginLogWriter::reopen()
|
|
{
|
|
if (m_fileHandle >= 0)
|
|
::close(m_fileHandle);
|
|
|
|
#ifdef WIN_NT
|
|
HANDLE hFile = CreateFile(
|
|
m_fileName.c_str(),
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
NULL,
|
|
OPEN_ALWAYS,
|
|
0, // FILE_FLAG_SEQUENTIAL_SCAN,
|
|
NULL
|
|
);
|
|
m_fileHandle = _open_osfhandle((intptr_t) hFile, 0);
|
|
#else
|
|
m_fileHandle = ::open(m_fileName.c_str(), O_CREAT | O_APPEND | O_RDWR, S_IREAD | S_IWRITE);
|
|
#endif
|
|
|
|
if (m_fileHandle < 0)
|
|
checkErrno("open");
|
|
}
|
|
|
|
size_t PluginLogWriter::write(const void* buf, size_t size)
|
|
{
|
|
#ifdef WIN_NT
|
|
Guard guard(this);
|
|
#endif
|
|
|
|
if (m_fileHandle < 0)
|
|
reopen();
|
|
|
|
FB_UINT64 fileSize = seekToEnd();
|
|
if (m_maxSize && (fileSize > m_maxSize))
|
|
{
|
|
reopen();
|
|
fileSize = seekToEnd();
|
|
}
|
|
|
|
if (m_maxSize && (fileSize > m_maxSize))
|
|
{
|
|
const TimeStamp stamp(TimeStamp::getCurrentTimeStamp());
|
|
struct tm times;
|
|
stamp.decode(×);
|
|
|
|
PathName newName;
|
|
const size_t last_dot_pos = m_fileName.rfind(".");
|
|
if (last_dot_pos > 0)
|
|
{
|
|
PathName log_name = m_fileName.substr(0, last_dot_pos);
|
|
PathName log_ext = m_fileName.substr(last_dot_pos + 1, m_fileName.length());
|
|
newName.printf("%s.%04d-%02d-%02dT%02d-%02d-%02d.%s", log_name.c_str(), times.tm_year + 1900,
|
|
times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec, log_ext.c_str());
|
|
}
|
|
else
|
|
{
|
|
newName.printf("%s.%04d-%02d-%02dT%02d-%02d-%02d", m_fileName.c_str(), times.tm_year + 1900,
|
|
times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec);
|
|
}
|
|
|
|
#ifdef WIN_NT
|
|
// hvlad: sad, but MSDN said "rename" returns EACCES when newName already
|
|
// exists. Therefore we can't just check "rename" result for EEXIST and need
|
|
// to write platform-dependent code. In reality, "rename" returns EEXIST to
|
|
// me, not EACCES, strange...
|
|
if (!MoveFile(m_fileName.c_str(), newName.c_str()))
|
|
{
|
|
const DWORD dwError = GetLastError();
|
|
if (dwError != ERROR_ALREADY_EXISTS && dwError != ERROR_FILE_NOT_FOUND)
|
|
{
|
|
fatal_exception::raiseFmt("PluginLogWriter: MoveFile failed on file \"%s\". Error is : %d",
|
|
m_fileName.c_str(), dwError);
|
|
}
|
|
}
|
|
#else
|
|
if (rename(m_fileName.c_str(), newName.c_str()))
|
|
{
|
|
const int iErr = errno;
|
|
if (iErr != ENOENT && iErr != EEXIST)
|
|
checkErrno("rename");
|
|
}
|
|
#endif
|
|
|
|
reopen();
|
|
seekToEnd();
|
|
}
|
|
|
|
const size_t written = ::write(m_fileHandle, buf, size);
|
|
if (written != size)
|
|
checkErrno("write");
|
|
|
|
return written;
|
|
}
|
|
|
|
void PluginLogWriter::checkErrno(const char* operation)
|
|
{
|
|
if (errno == 0)
|
|
return;
|
|
|
|
const char* strErr;
|
|
#ifdef WIN_NT
|
|
strErr = strerror(errno);
|
|
#else
|
|
char buff[256];
|
|
strerror_r(errno, buff, sizeof(buff));
|
|
strErr = buff;
|
|
#endif
|
|
fatal_exception::raiseFmt("PluginLogWriter: operation \"%s\" failed on file \"%s\". Error is : %s",
|
|
operation, m_fileName.c_str(), strErr);
|
|
}
|
|
|
|
#ifdef WIN_NT
|
|
void PluginLogWriter::checkMutex(const TEXT* string, int state)
|
|
{
|
|
if (state)
|
|
{
|
|
TEXT msg[BUFFER_TINY];
|
|
|
|
sprintf(msg, "PluginLogWriter: mutex %s error, status = %d", string, state);
|
|
gds__log(msg);
|
|
|
|
fprintf(stderr, "%s\n", msg);
|
|
exit(FINI_ERROR);
|
|
}
|
|
}
|
|
|
|
void PluginLogWriter::lock()
|
|
{
|
|
checkMutex("lock", ISC_mutex_lock(&m_mutex));
|
|
}
|
|
|
|
void PluginLogWriter::unlock()
|
|
{
|
|
checkMutex("unlock", ISC_mutex_unlock(&m_mutex));
|
|
}
|
|
#endif // WIN_NT
|