Skip to content

Commit

Permalink
MDEV-15895 : make Innodb merge temp tables use pfs_os_file_t for
Browse files Browse the repository at this point in the history
file IO, rather than int.

On Windows, it is suboptimal to depend on C runtime, as it has limited
number of file descriptors. This change eliminates
os_file_read_no_error_handling_int_fd(), os_file_write_int_fd(),
OS_FILE_FROM_FD() macro.
  • Loading branch information
vaintroub committed Apr 17, 2018
1 parent 7d991fe commit 321771f
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 264 deletions.
88 changes: 46 additions & 42 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2410,19 +2410,18 @@ static int mysql_tmpfile_path(const char *path, const char *prefix)
path. If the path is NULL, then it will be created in tmpdir.
@param[in] path location for creating temporary file
@return temporary file descriptor, or < 0 on error */
int
os_file_t
innobase_mysql_tmpfile(
const char* path)
{
#ifdef WITH_INNODB_DISALLOW_WRITES
os_event_wait(srv_allow_writes_event);
#endif /* WITH_INNODB_DISALLOW_WRITES */
int fd2 = -1;
File fd;

DBUG_EXECUTE_IF(
"innobase_tmpfile_creation_failure",
return(-1);
return(OS_FILE_CLOSED);
);

if (path == NULL) {
Expand All @@ -2431,50 +2430,55 @@ innobase_mysql_tmpfile(
fd = mysql_tmpfile_path(path, "ib");
}

if (fd >= 0) {
/* Copy the file descriptor, so that the additional resources
allocated by create_temp_file() can be freed by invoking
my_close().
if (fd < 0)
return OS_FILE_CLOSED;

/* Copy the file descriptor, so that the additional resources
allocated by create_temp_file() can be freed by invoking
my_close().

Because the file descriptor returned by this function
will be passed to fdopen(), it will be closed by invoking
fclose(), which in turn will invoke close() instead of
my_close(). */
Because the file descriptor returned by this function
will be passed to fdopen(), it will be closed by invoking
fclose(), which in turn will invoke close() instead of
my_close(). */

#ifdef _WIN32
/* Note that on Windows, the integer returned by mysql_tmpfile
has no relation to C runtime file descriptor. Here, we need
to call my_get_osfhandle to get the HANDLE and then convert it
to C runtime filedescriptor. */
{
HANDLE hFile = my_get_osfhandle(fd);
HANDLE hDup;
BOOL bOK = DuplicateHandle(
GetCurrentProcess(),
hFile, GetCurrentProcess(),
&hDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
if (bOK) {
fd2 = _open_osfhandle((intptr_t) hDup, 0);
} else {
my_osmaperr(GetLastError());
fd2 = -1;
}
}
/* Note that on Windows, the integer returned by mysql_tmpfile
has no relation to C runtime file descriptor. Here, we need
to call my_get_osfhandle to get the HANDLE and then convert it
to C runtime filedescriptor. */

HANDLE hFile = my_get_osfhandle(fd);
HANDLE hDup;
BOOL bOK = DuplicateHandle(
GetCurrentProcess(),
hFile, GetCurrentProcess(),
&hDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
my_close(fd, MYF(MY_WME));

if (!bOK) {
my_osmaperr(GetLastError());
goto error;
}
return hDup;
#else
fd2 = dup(fd);
int fd2 = dup(fd);
my_close(fd, MYF(MY_WME));
if (fd2 < 0) {
set_my_errno(errno);
goto error;
}
return fd2;
#endif
if (fd2 < 0) {
char errbuf[MYSYS_STRERROR_SIZE];
DBUG_PRINT("error",("Got error %d on dup",fd2));
set_my_errno(errno);
my_error(EE_OUT_OF_FILERESOURCES,
MYF(0),
"ib*", errno,
my_strerror(errbuf, sizeof(errbuf), errno));
}
my_close(fd, MYF(MY_WME));
}
return(fd2);

error:
char errbuf[MYSYS_STRERROR_SIZE];

my_error(EE_OUT_OF_FILERESOURCES,
MYF(0),
"ib*", errno,
my_strerror(errbuf, sizeof(errbuf), errno));
return (OS_FILE_CLOSED);
}

/*********************************************************************//**
Expand Down
21 changes: 2 additions & 19 deletions storage/innobase/include/os0file.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,6 @@ the OS actually supports it: Win 95 does not, NT does. */
/** File handle */
typedef HANDLE os_file_t;

/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
# define OS_FILE_FROM_FD(fd) (HANDLE) _get_osfhandle(fd)

#else /* _WIN32 */

Expand All @@ -80,14 +76,9 @@ typedef DIR* os_file_dir_t; /*!< directory stream */
/** File handle */
typedef int os_file_t;

/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
# define OS_FILE_FROM_FD(fd) fd

#endif /* _WIN32 */

static const os_file_t OS_FILE_CLOSED = os_file_t(~0);
static const os_file_t OS_FILE_CLOSED = IF_WIN(os_file_t(INVALID_HANDLE_VALUE),-1);

/** File descriptor with optional PERFORMANCE_SCHEMA instrumentation */
struct pfs_os_file_t
Expand Down Expand Up @@ -843,18 +834,10 @@ The wrapper functions have the prefix of "innodb_". */
pfs_os_file_read_no_error_handling_func( \
type, file, buf, offset, n, o, __FILE__, __LINE__)

# define os_file_read_no_error_handling_int_fd(type, file, buf, offset, n) \
pfs_os_file_read_no_error_handling_int_fd_func( \
type, file, buf, offset, n, __FILE__, __LINE__)

# define os_file_write(type, name, file, buf, offset, n) \
pfs_os_file_write_func(type, name, file, buf, offset, \
n, __FILE__, __LINE__)

# define os_file_write_int_fd(type, name, file, buf, offset, n) \
pfs_os_file_write_int_fd_func(type, name, file, buf, offset, \
n, __FILE__, __LINE__)

# define os_file_flush(file) \
pfs_os_file_flush_func(file, __FILE__, __LINE__)

Expand Down Expand Up @@ -1564,7 +1547,7 @@ path. If the path is NULL then it will be created on --tmpdir location.
This function is defined in ha_innodb.cc.
@param[in] path location for creating temporary file
@return temporary file descriptor, or < 0 on error */
int
os_file_t
innobase_mysql_tmpfile(
const char* path);

Expand Down
88 changes: 0 additions & 88 deletions storage/innobase/include/os0file.ic
Original file line number Diff line number Diff line change
Expand Up @@ -340,49 +340,6 @@ pfs_os_file_read_no_error_handling_func(
return(result);
}

/** NOTE! Please use the corresponding macro
os_file_read_no_error_handling_int_fd() to request
a synchronous read operation.
@param[in] type read request
@param[in] file file handle
@param[out] buf buffer where to read
@param[in] offset file offset where to read
@param[in] n number of bytes to read
@param[in] src_file caller file name
@param[in] src_line caller line number
@return whether the request was successful */
UNIV_INLINE
bool
pfs_os_file_read_no_error_handling_int_fd_func(
const IORequest& type,
int file,
void* buf,
os_offset_t offset,
ulint n,
const char* src_file,
uint src_line)
{
PSI_file_locker_state state;

PSI_file_locker* locker = PSI_FILE_CALL(
get_thread_file_descriptor_locker)(
&state, file, PSI_FILE_READ);
if (locker != NULL) {
PSI_FILE_CALL(start_file_wait)(
locker, n,
__FILE__, __LINE__);
}

bool success = DB_SUCCESS == os_file_read_no_error_handling_func(
type, OS_FILE_FROM_FD(file), buf, offset, n, NULL);

if (locker != NULL) {
PSI_FILE_CALL(end_file_wait)(locker, n);
}

return(success);
}

/** NOTE! Please use the corresponding macro os_file_write(), not directly
this function!
This is the performance schema instrumented wrapper function for
Expand Down Expand Up @@ -425,51 +382,6 @@ pfs_os_file_write_func(
return(result);
}

/** NOTE! Please use the corresponding macro os_file_write_int_fd(),
not directly this function!
This is the performance schema instrumented wrapper function for
os_file_write_int_fd() which requests a synchronous write operation.
@param[in] type write request
@param[in] name file name
@param[in] file file handle
@param[in] buf buffer to write
@param[in] offset file offset
@param[in] n number of bytes
@param[in] src_file file name where func invoked
@param[in] src_line line where the func invoked
@return whether the request was successful */
UNIV_INLINE
bool
pfs_os_file_write_int_fd_func(
const IORequest& type,
const char* name,
int file,
const void* buf,
os_offset_t offset,
ulint n,
const char* src_file,
uint src_line)
{
PSI_file_locker_state state;
struct PSI_file_locker* locker;

locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
&state, file, PSI_FILE_WRITE);
if (locker != NULL) {
PSI_FILE_CALL(start_file_wait)(
locker, n,
__FILE__, __LINE__);
}

bool success = DB_SUCCESS == os_file_write_func(
type, name, OS_FILE_FROM_FD(file), buf, offset, n);

if (locker != NULL) {
PSI_FILE_CALL(end_file_wait)(locker, n);
}

return(success);
}

/** NOTE! Please use the corresponding macro os_file_flush(), not directly
this function!
Expand Down
16 changes: 8 additions & 8 deletions storage/innobase/include/row0merge.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ struct row_merge_buf_t {

/** Information about temporary files used in merge sort */
struct merge_file_t {
int fd; /*!< file descriptor */
pfs_os_file_t fd; /*!< file descriptor */
ulint offset; /*!< file offset (end of file) */
ib_uint64_t n_rec; /*!< number of records in the file */
};
Expand Down Expand Up @@ -193,7 +193,7 @@ row_merge_drop_temp_indexes(void);
UNIV_PFS_IO defined, register the file descriptor with Performance Schema.
@param[in] path location for creating temporary merge files, or NULL
@return File descriptor */
int
pfs_os_file_t
row_merge_file_create_low(
const char* path)
MY_ATTRIBUTE((warn_unused_result));
Expand All @@ -203,7 +203,7 @@ if UNIV_PFS_IO is defined. */
void
row_merge_file_destroy_low(
/*=======================*/
int fd); /*!< in: merge file descriptor */
const pfs_os_file_t& fd); /*!< in: merge file descriptor */

/*********************************************************************//**
Provide a new pathname for a table that is being renamed if it belongs to
Expand Down Expand Up @@ -372,7 +372,7 @@ UNIV_INTERN
bool
row_merge_write(
/*============*/
int fd, /*!< in: file descriptor */
const pfs_os_file_t& fd, /*!< in: file descriptor */
ulint offset, /*!< in: offset where to write,
in number of row_merge_block_t elements */
const void* buf, /*!< in: data */
Expand All @@ -393,7 +393,7 @@ row_merge_buf_empty(
@param[out] merge_file merge file structure
@param[in] path location for creating temporary file, or NULL
@return file descriptor, or -1 on failure */
int
pfs_os_file_t
row_merge_file_create(
merge_file_t* merge_file,
const char* path)
Expand Down Expand Up @@ -421,7 +421,7 @@ row_merge_sort(
const row_merge_dup_t* dup,
merge_file_t* file,
row_merge_block_t* block,
int* tmpfd,
pfs_os_file_t* tmpfd,
const bool update_progress,
const double pct_progress,
const double pct_cost,
Expand Down Expand Up @@ -460,7 +460,7 @@ row_merge_file_destroy(
bool
row_merge_read(
/*===========*/
int fd, /*!< in: file descriptor */
const pfs_os_file_t& fd, /*!< in: file descriptor */
ulint offset, /*!< in: offset where to read
in number of row_merge_block_t
elements */
Expand All @@ -479,7 +479,7 @@ row_merge_read_rec(
mrec_buf_t* buf, /*!< in/out: secondary buffer */
const byte* b, /*!< in: pointer to record */
const dict_index_t* index, /*!< in: index of the record */
int fd, /*!< in: file descriptor */
const pfs_os_file_t& fd, /*!< in: file descriptor */
ulint* foffs, /*!< in/out: file offset */
const mrec_t** mrec, /*!< out: pointer to merge record,
or NULL on end of list
Expand Down
21 changes: 15 additions & 6 deletions storage/innobase/os/os0file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1253,21 +1253,30 @@ os_file_create_tmpfile()
{
FILE* file = NULL;
WAIT_ALLOW_WRITES();
int fd = innobase_mysql_tmpfile(NULL);
os_file_t fd = innobase_mysql_tmpfile(NULL);

if (fd >= 0) {
if (fd != OS_FILE_CLOSED) {
#ifdef _WIN32
int crt_fd = _open_osfhandle((intptr_t)HANDLE(fd), 0);
if (crt_fd != -1) {
file = fdopen(crt_fd, "w+b");
if (!file) {
close(crt_fd);
}
}
#else
file = fdopen(fd, "w+b");
if (!file) {
close(fd);
}
#endif
}

if (file == NULL) {

ib::error()
<< "Unable to create temporary file; errno: "
<< errno;

if (fd >= 0) {
close(fd);
}
}

return(file);
Expand Down
Loading

0 comments on commit 321771f

Please sign in to comment.