|
From: <hv...@us...> - 2014-06-10 09:01:01
|
Revision: 59679
http://sourceforge.net/p/firebird/code/59679
Author: hvlad
Date: 2014-06-10 09:00:58 +0000 (Tue, 10 Jun 2014)
Log Message:
-----------
Front ported support for fallocate() call on Linux.
Front ported improvement CORE-4443 : Use fast file grow on those Linux systems which supports it
Modified Paths:
--------------
firebird/trunk/configure.ac
firebird/trunk/src/jrd/os/pio.h
firebird/trunk/src/jrd/os/posix/unix.cpp
firebird/trunk/src/jrd/pag.cpp
firebird/trunk/src/jrd/pag.h
Modified: firebird/trunk/configure.ac
===================================================================
--- firebird/trunk/configure.ac 2014-06-10 07:13:34 UTC (rev 59678)
+++ firebird/trunk/configure.ac 2014-06-10 09:00:58 UTC (rev 59679)
@@ -690,6 +690,7 @@
AC_CHECK_HEADERS(langinfo.h)
AC_CHECK_HEADERS(iconv.h)
AC_CHECK_HEADERS(libio.h)
+AC_CHECK_HEADERS(linux/falloc.h)
dnl check for ICU presence
AC_CHECK_HEADER(unicode/ucnv.h,,AC_MSG_ERROR(ICU support not found - please install development ICU package))
Modified: firebird/trunk/src/jrd/os/pio.h
===================================================================
--- firebird/trunk/src/jrd/os/pio.h 2014-06-10 07:13:34 UTC (rev 59678)
+++ firebird/trunk/src/jrd/os/pio.h 2014-06-10 09:00:58 UTC (rev 59679)
@@ -94,6 +94,7 @@
const USHORT FIL_no_fs_cache = 2; // not using file system cache
const USHORT FIL_readonly = 4; // file opened in readonly mode
const USHORT FIL_sh_write = 8; // file opened in shared write mode
+const USHORT FIL_no_fast_extend = 16; // file not supports fast extending
// Physical IO trace events
Modified: firebird/trunk/src/jrd/os/posix/unix.cpp
===================================================================
--- firebird/trunk/src/jrd/os/posix/unix.cpp 2014-06-10 07:13:34 UTC (rev 59678)
+++ firebird/trunk/src/jrd/os/posix/unix.cpp 2014-06-10 09:00:58 UTC (rev 59679)
@@ -45,6 +45,9 @@
#ifdef HAVE_AIO_H
#include <aio.h>
#endif
+#ifdef HAVE_LINUX_FALLOC_H
+#include <linux/falloc.h>
+#endif
#include "../jrd/jrd.h"
#include "../jrd/os/pio.h"
@@ -291,7 +294,7 @@
}
-void PIO_extend(Database* dbb, jrd_file* /*main_file*/, const ULONG /*extPages*/, const USHORT /*pageSize*/)
+void PIO_extend(Database* dbb, jrd_file* main_file, const ULONG extPages, const USHORT pageSize)
{
/**************************************
*
@@ -303,6 +306,56 @@
* Extend file by extPages pages of pageSize size.
*
**************************************/
+
+#ifdef HAVE_LINUX_FALLOC_H
+ ULONG leftPages = extPages;
+ for (jrd_file* file = main_file; file && leftPages; file = file->fil_next)
+ {
+ const ULONG filePages = PIO_get_number_of_pages(file, pageSize);
+ const ULONG fileMaxPages = (file->fil_max_page == MAX_ULONG) ?
+ MAX_ULONG : file->fil_max_page - file->fil_min_page + 1;
+ if (filePages < fileMaxPages)
+ {
+ if (file->fil_flags & FIL_no_fast_extend)
+ return;
+
+ const ULONG extendBy = MIN(fileMaxPages - filePages + file->fil_fudge, leftPages);
+
+ int r;
+ for (r = 0; r < IO_RETRY; r++)
+ {
+ int err = fallocate(file->fil_desc, 0, filePages * pageSize, extendBy * pageSize);
+ if (err == 0)
+ break;
+
+ err = errno;
+ if (SYSCALL_INTERRUPTED(err))
+ continue;
+
+ if (err == EOPNOTSUPP || err == ENOSYS)
+ file->fil_flags |= FIL_no_fast_extend;
+ else
+ unix_error("fallocate", file, isc_io_write_err);
+ return;
+ }
+
+ if (r == IO_RETRY)
+ {
+#ifdef DEV_BUILD
+ fprintf(stderr, "PIO_extend: retry count exceeded\n");
+ fflush(stderr);
+#endif
+ unix_error("fallocate_retry", file, isc_io_write_err);
+ return;
+ }
+
+ leftPages -= extendBy;
+ }
+ }
+#else
+ main_file->fil_flags |= FIL_no_fast_extend;
+#endif // HAVE_LINUX_FALLOC_H
+
// not implemented
return;
}
Modified: firebird/trunk/src/jrd/pag.cpp
===================================================================
--- firebird/trunk/src/jrd/pag.cpp 2014-06-10 07:13:34 UTC (rev 59678)
+++ firebird/trunk/src/jrd/pag.cpp 2014-06-10 09:00:58 UTC (rev 59679)
@@ -640,7 +640,7 @@
// At this point we ensure database has at least "initialized" pages
// allocated. To avoid file growth by few pages when all this space
// will be used, extend file up to initialized + next_init_pages now
- pageSpace->extend(tdbb, initialized + next_init_pages);
+ pageSpace->extend(tdbb, initialized + next_init_pages, false);
}
break; // Found a page and successfully fake-ed it
@@ -2039,7 +2039,7 @@
return pgSpace->lastUsedPage();
}
-bool PageSpace::extend(thread_db* tdbb, const ULONG pageNum)
+bool PageSpace::extend(thread_db* tdbb, const ULONG pageNum, const bool forceSize)
{
/**************************************
*
@@ -2051,12 +2051,16 @@
* If "DatabaseGrowthIncrement" is less than MIN_EXTEND_BYTES then don't
* extend file(s)
*
+ * If forceSize is true, extend file up to pageNum pages (despite of value
+ * of "DatabaseGrowthIncrement") and don't make attempts to extend by less
+ * pages.
+ *
**************************************/
fb_assert(dbb == tdbb->getDatabase());
const int MAX_EXTEND_BYTES = dbb->dbb_config->getDatabaseGrowthIncrement();
- if (pageNum < maxPageNumber || MAX_EXTEND_BYTES < MIN_EXTEND_BYTES)
+ if (pageNum < maxPageNumber || MAX_EXTEND_BYTES < MIN_EXTEND_BYTES && !forceSize)
return true;
if (pageNum >= maxAlloc())
@@ -2071,6 +2075,7 @@
while (true)
{
+ const ULONG oldMaxPageNumber = maxPageNumber;
try
{
PIO_extend(dbb, file, extPages, dbb->dbb_page_size);
@@ -2078,10 +2083,16 @@
}
catch (const status_exception&)
{
- if (extPages > reqPages)
+ if (extPages > reqPages && !forceSize)
{
+ fb_utils::init_status(tdbb->tdbb_status_vector);
+
+ // if file was extended, return, else try to extend by less pages
+
+ if (oldMaxPageNumber < maxAlloc())
+ return true;
+
extPages = MAX(reqPages, extPages / 2);
- fb_utils::init_status(tdbb->tdbb_status_vector);
}
else
{
Modified: firebird/trunk/src/jrd/pag.h
===================================================================
--- firebird/trunk/src/jrd/pag.h 2014-06-10 07:13:34 UTC (rev 59678)
+++ firebird/trunk/src/jrd/pag.h 2014-06-10 09:00:58 UTC (rev 59679)
@@ -120,7 +120,7 @@
static ULONG lastUsedPage(const Database* dbb);
// extend page space
- bool extend(thread_db*, const ULONG);
+ bool extend(thread_db*, const ULONG, const bool);
// get SCN's page number
ULONG getSCNPageNum(ULONG sequence);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|