diff --git a/src/common/classes/File.h b/src/common/classes/File.h index 13f2949e16..83b4b8f7e8 100644 --- a/src/common/classes/File.h +++ b/src/common/classes/File.h @@ -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 buffer; +}; + } // namespace #endif // CLASSES_FILE_H diff --git a/src/common/classes/TempFile.cpp b/src/common/classes/TempFile.cpp index ff06c21c4c..e9bfdfeb67 100644 --- a/src/common/classes/TempFile.cpp +++ b/src/common/classes/TempFile.cpp @@ -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 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; diff --git a/src/jrd/os/pio.h b/src/jrd/os/pio.h index c150442d6d..db2a299290 100644 --- a/src/jrd/os/pio.h +++ b/src/jrd/os/pio.h @@ -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 zeroArray; - char* const zeroBuff; -}; - } //namespace Jrd #endif // JRD_PIO_H diff --git a/src/jrd/os/posix/unix.cpp b/src/jrd/os/posix/unix.cpp index 35eae78de3..d43f4894b7 100644 --- a/src/jrd/os/posix/unix.cpp +++ b/src/jrd/os/posix/unix.cpp @@ -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 zeros; +static Firebird::InitInstance 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); diff --git a/src/jrd/os/win32/winnt.cpp b/src/jrd/os/win32/winnt.cpp index e513c8b509..f2035de0be 100644 --- a/src/jrd/os/win32/winnt.cpp +++ b/src/jrd/os/win32/winnt.cpp @@ -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 zeros; +static Firebird::InitInstance 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;