mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 08:43:03 +01:00
Fixed CORE-2422: Server doesn't switch between multiple entries configured in TempDirectories when some of them is out of free space.
Moved the common code to File.h.
This commit is contained in:
parent
12a4f93f23
commit
21971f03a0
@ -23,6 +23,8 @@
|
||||
#ifndef CLASSES_FILE_H
|
||||
#define CLASSES_FILE_H
|
||||
|
||||
#include "../common/classes/array.h"
|
||||
|
||||
#if !defined(SOLARIS) && !defined(AIX)
|
||||
typedef FB_UINT64 offset_t;
|
||||
#endif
|
||||
@ -42,6 +44,24 @@ public:
|
||||
virtual offset_t getSize() const = 0;
|
||||
};
|
||||
|
||||
class ZeroBuffer
|
||||
{
|
||||
static const size_t DEFAULT_SIZE = 1024 * 256;
|
||||
|
||||
public:
|
||||
explicit ZeroBuffer(MemoryPool& p, size_t size = DEFAULT_SIZE)
|
||||
: buffer(p)
|
||||
{
|
||||
memset(buffer.getBuffer(size), 0, size);
|
||||
}
|
||||
|
||||
const char* getBuffer() const { return buffer.begin(); }
|
||||
size_t getSize() const { return buffer.getCount(); }
|
||||
|
||||
private:
|
||||
Firebird::Array<char> buffer;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // CLASSES_FILE_H
|
||||
|
@ -46,6 +46,7 @@
|
||||
|
||||
#include "../jrd/gdsassert.h"
|
||||
#include "../jrd/os/path_utils.h"
|
||||
#include "../common/classes/init.h"
|
||||
|
||||
#include "../common/classes/TempFile.h"
|
||||
|
||||
@ -67,6 +68,10 @@ static const char* const NAME_PATTERN = "XXXXXX";
|
||||
static const char* const NAME_LETTERS = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
static const size_t MAX_TRIES = 256;
|
||||
|
||||
// we need a class here only to return memory on shutdown and avoid
|
||||
// false memory leak reports
|
||||
static Firebird::InitInstance<ZeroBuffer> zeros;
|
||||
|
||||
//
|
||||
// TempFile::getTempPath
|
||||
//
|
||||
@ -115,9 +120,8 @@ PathName TempFile::create(const PathName& prefix, const PathName& directory)
|
||||
TempFile file(*getDefaultMemoryPool(), prefix, directory, false);
|
||||
filename = file.getName();
|
||||
}
|
||||
catch (const Exception&) {
|
||||
// do nothing
|
||||
}
|
||||
catch (const Exception&)
|
||||
{} // do nothing
|
||||
|
||||
return filename;
|
||||
}
|
||||
@ -171,7 +175,7 @@ void TempFile::init(const PathName& directory, const PathName& prefix)
|
||||
}
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
system_call_failed::raise("CreateFile");
|
||||
system_error::raise("CreateFile");
|
||||
}
|
||||
#else
|
||||
filename += prefix;
|
||||
@ -182,7 +186,7 @@ void TempFile::init(const PathName& directory, const PathName& prefix)
|
||||
#else
|
||||
if (!mktemp(filename.begin()))
|
||||
{
|
||||
system_call_failed::raise("mktemp");
|
||||
system_error::raise("mktemp");
|
||||
}
|
||||
|
||||
do {
|
||||
@ -192,7 +196,7 @@ void TempFile::init(const PathName& directory, const PathName& prefix)
|
||||
|
||||
if (handle == -1)
|
||||
{
|
||||
system_call_failed::raise("open");
|
||||
system_error::raise("open");
|
||||
}
|
||||
|
||||
if (doUnlink)
|
||||
@ -241,13 +245,13 @@ void TempFile::seek(const offset_t offset)
|
||||
SetFilePointer(handle, (LONG) liOffset.LowPart, &liOffset.HighPart, FILE_BEGIN);
|
||||
if (seek_result == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
|
||||
{
|
||||
system_call_failed::raise("SetFilePointer");
|
||||
system_error::raise("SetFilePointer");
|
||||
}
|
||||
#else
|
||||
const off_t seek_result = ::lseek(handle, (off_t) offset, SEEK_SET);
|
||||
if (seek_result == (off_t) -1)
|
||||
{
|
||||
system_call_failed::raise("lseek");
|
||||
system_error::raise("lseek");
|
||||
}
|
||||
#endif
|
||||
position = offset;
|
||||
@ -263,7 +267,14 @@ void TempFile::seek(const offset_t offset)
|
||||
|
||||
void TempFile::extend(size_t delta)
|
||||
{
|
||||
seek(size + delta);
|
||||
const char* const buffer = zeros().getBuffer();
|
||||
const size_t bufferSize = zeros().getSize();
|
||||
const size_t newSize = size + delta;
|
||||
for (size_t offset = size; offset < newSize; offset += bufferSize)
|
||||
{
|
||||
const size_t length = MIN(newSize - size, bufferSize);
|
||||
write(offset, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -280,13 +291,13 @@ size_t TempFile::read(offset_t offset, void* buffer, size_t length)
|
||||
DWORD bytes = 0;
|
||||
if (!ReadFile(handle, buffer, length, &bytes, NULL) || bytes != length)
|
||||
{
|
||||
system_call_failed::raise("ReadFile");
|
||||
system_error::raise("ReadFile");
|
||||
}
|
||||
#else
|
||||
const int bytes = ::read(handle, buffer, length);
|
||||
if (bytes < 0 || size_t(bytes) != length)
|
||||
{
|
||||
system_call_failed::raise("read");
|
||||
system_error::raise("read");
|
||||
}
|
||||
#endif
|
||||
position += bytes;
|
||||
@ -307,13 +318,13 @@ size_t TempFile::write(offset_t offset, const void* buffer, size_t length)
|
||||
DWORD bytes = 0;
|
||||
if (!WriteFile(handle, buffer, length, &bytes, NULL) || bytes != length)
|
||||
{
|
||||
system_call_failed::raise("WriteFile");
|
||||
system_error::raise("WriteFile");
|
||||
}
|
||||
#else
|
||||
const int bytes = ::write(handle, buffer, length);
|
||||
if (bytes < 0 || size_t(bytes) != length)
|
||||
{
|
||||
system_call_failed::raise("write");
|
||||
system_error::raise("write");
|
||||
}
|
||||
#endif
|
||||
position += bytes;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "../jrd/thread_proto.h"
|
||||
#include "../common/classes/rwlock.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../common/classes/File.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
@ -122,25 +123,6 @@ const UCHAR PIOB_success = 2; /* I/O successfully completed */
|
||||
const UCHAR PIOB_pending = 4; /* Asynchronous I/O not yet completed */
|
||||
#endif
|
||||
|
||||
static const int ZERO_BUF_SIZE = 1024 * 128;
|
||||
|
||||
class HugeStaticBuffer
|
||||
{
|
||||
public:
|
||||
explicit HugeStaticBuffer(MemoryPool& p)
|
||||
: zeroArray(p),
|
||||
zeroBuff(zeroArray.getBuffer(ZERO_BUF_SIZE))
|
||||
{
|
||||
memset(zeroBuff, 0, ZERO_BUF_SIZE);
|
||||
}
|
||||
|
||||
const char* get() const { return zeroBuff; }
|
||||
|
||||
private:
|
||||
Firebird::Array<char> zeroArray;
|
||||
char* const zeroBuff;
|
||||
};
|
||||
|
||||
} //namespace Jrd
|
||||
|
||||
#endif // JRD_PIO_H
|
||||
|
@ -510,7 +510,7 @@ void PIO_header(Database* dbb, SCHAR * address, int length)
|
||||
|
||||
// we need a class here only to return memory on shutdown and avoid
|
||||
// false memory leak reports
|
||||
static InitInstance<HugeStaticBuffer> zeros;
|
||||
static Firebird::InitInstance<ZeroBuffer> zeros;
|
||||
|
||||
|
||||
USHORT PIO_init_data(Database* dbb, jrd_file* main_file, ISC_STATUS* status_vector,
|
||||
@ -526,6 +526,8 @@ USHORT PIO_init_data(Database* dbb, jrd_file* main_file, ISC_STATUS* status_vect
|
||||
* Initialize tail of file with zeros
|
||||
*
|
||||
**************************************/
|
||||
const char* const zero_buff = zeros().getBuffer();
|
||||
const size_t zero_buff_size = zeros().getSize();
|
||||
|
||||
// Fake buffer, used in seek_file. Page space ID have no matter there
|
||||
// as we already know file to work with
|
||||
@ -553,7 +555,7 @@ USHORT PIO_init_data(Database* dbb, jrd_file* main_file, ISC_STATUS* status_vect
|
||||
for (ULONG i = startPage; i < startPage + initBy; )
|
||||
{
|
||||
bdb.bdb_page = PageNumber(0, i);
|
||||
USHORT write_pages = ZERO_BUF_SIZE / dbb->dbb_page_size;
|
||||
USHORT write_pages = zero_buff_size / dbb->dbb_page_size;
|
||||
if (write_pages > leftPages)
|
||||
write_pages = leftPages;
|
||||
|
||||
@ -564,7 +566,7 @@ USHORT PIO_init_data(Database* dbb, jrd_file* main_file, ISC_STATUS* status_vect
|
||||
{
|
||||
if (!(file = seek_file(file, &bdb, &offset, status_vector)))
|
||||
return false;
|
||||
if ((written = pwrite(file->fil_desc, zeros().get(), to_write, LSEEK_OFFSET_CAST offset)) == to_write)
|
||||
if ((written = pwrite(file->fil_desc, zero_buff, to_write, LSEEK_OFFSET_CAST offset)) == to_write)
|
||||
break;
|
||||
if (written == (SLONG) -1 && !SYSCALL_INTERRUPTED(errno))
|
||||
return unix_error("write", file, isc_io_write_err, status_vector);
|
||||
|
@ -460,7 +460,7 @@ void PIO_header(Database* dbb, SCHAR* address, int length)
|
||||
|
||||
// we need a class here only to return memory on shutdown and avoid
|
||||
// false memory leak reports
|
||||
static Firebird::InitInstance<HugeStaticBuffer> zeros;
|
||||
static Firebird::InitInstance<ZeroBuffer> zeros;
|
||||
|
||||
|
||||
USHORT PIO_init_data(Database* dbb, jrd_file* main_file, ISC_STATUS* status_vector,
|
||||
@ -476,7 +476,8 @@ USHORT PIO_init_data(Database* dbb, jrd_file* main_file, ISC_STATUS* status_vect
|
||||
* Initialize tail of file with zeros
|
||||
*
|
||||
**************************************/
|
||||
const char* const zero_buff = zeros().get();
|
||||
const char* const zero_buff = zeros().getBuffer();
|
||||
const size_t zero_buff_size = zeros().getSize();
|
||||
|
||||
Database::Checkout dcoHolder(dbb);
|
||||
FileExtendLockGuard extLock(main_file->fil_ext_lock, false);
|
||||
@ -505,7 +506,7 @@ USHORT PIO_init_data(Database* dbb, jrd_file* main_file, ISC_STATUS* status_vect
|
||||
for (ULONG i = startPage; i < startPage + initBy; )
|
||||
{
|
||||
bdb.bdb_page = PageNumber(0, i);
|
||||
USHORT write_pages = ZERO_BUF_SIZE / dbb->dbb_page_size;
|
||||
USHORT write_pages = zero_buff_size / dbb->dbb_page_size;
|
||||
if (write_pages > leftPages)
|
||||
write_pages = leftPages;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user