Commit 321771f8 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-15895 : make Innodb merge temp tables use pfs_os_file_t for

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.
parent 7d991feb
......@@ -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) {
......@@ -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);
}
/*********************************************************************//**
......
......@@ -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 */
......@@ -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
......@@ -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__)
......@@ -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);
......
......@@ -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
......@@ -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!
......
......@@ -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 */
};
......@@ -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));
......@@ -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
......@@ -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 */
......@@ -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)
......@@ -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,
......@@ -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 */
......@@ -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
......
......@@ -1253,10 +1253,23 @@ 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) {
......@@ -1264,10 +1277,6 @@ os_file_create_tmpfile()
ib::error()
<< "Unable to create temporary file; errno: "
<< errno;
if (fd >= 0) {
close(fd);
}
}
return(file);
......
......@@ -255,7 +255,7 @@ row_fts_psort_info_init(
dup->index);
if (row_merge_file_create(psort_info[j].merge_file[i],
path) < 0) {
path) == OS_FILE_CLOSED) {
goto func_exit;
}
......@@ -776,7 +776,7 @@ DECLARE_THREAD(fts_parallel_tokenization)(
merge_file_t** merge_file;
row_merge_block_t** block;
row_merge_block_t** crypt_block;
int tmpfd[FTS_NUM_AUX_INDEX];
pfs_os_file_t tmpfd[FTS_NUM_AUX_INDEX];
ulint mycount[FTS_NUM_AUX_INDEX];
ib_uint64_t total_rec = 0;
ulint num_doc_processed = 0;
......@@ -1029,7 +1029,7 @@ DECLARE_THREAD(fts_parallel_tokenization)(
}
tmpfd[i] = row_merge_file_create_low(path);
if (tmpfd[i] < 0) {
if (tmpfd[i] == OS_FILE_CLOSED) {
error = DB_OUT_OF_MEMORY;
goto func_exit;
}
......@@ -1041,12 +1041,12 @@ DECLARE_THREAD(fts_parallel_tokenization)(
crypt_block[i], table->space->id);
if (error != DB_SUCCESS) {
close(tmpfd[i]);
os_file_close(tmpfd[i]);
goto func_exit;
}
total_rec += merge_file[i]->n_rec;
close(tmpfd[i]);
os_file_close(tmpfd[i]);
}
func_exit:
......@@ -1570,7 +1570,7 @@ row_fts_merge_insert(
ib_alloc_t* heap_alloc;
ulint i;
mrec_buf_t** buf;
int* fd;
pfs_os_file_t* fd;
byte** block;
byte** crypt_block;
const mrec_t** mrec;
......@@ -1612,7 +1612,7 @@ row_fts_merge_insert(
heap, sizeof(*offsets) * fts_sort_pll_degree);
buf = (mrec_buf_t**) mem_heap_alloc(
heap, sizeof(*buf) * fts_sort_pll_degree);
fd = (int*) mem_heap_alloc(heap, sizeof(*fd) * fts_sort_pll_degree);
fd = (pfs_os_file_t*) mem_heap_alloc(heap, sizeof(*fd) * fts_sort_pll_degree);
block = (byte**) mem_heap_alloc(
heap, sizeof(*block) * fts_sort_pll_degree);
crypt_block = (byte**) mem_heap_alloc(
......
......@@ -171,7 +171,7 @@ When head.blocks == tail.blocks, the reader will access tail.block
directly. When also head.bytes == tail.bytes, both counts will be
reset to 0 and the file will be truncated. */
struct row_log_t {
int fd; /*!< file descriptor */
pfs_os_file_t fd; /*!< file descriptor */
ib_mutex_t mutex; /*!< mutex protecting error,
max_trx and tail */
page_no_map* blobs; /*!< map of page numbers of off-page columns
......@@ -226,18 +226,18 @@ struct row_log_t {
@param[in,out] log online rebuild log
@return true if success, false if not */
static MY_ATTRIBUTE((warn_unused_result))
int
pfs_os_file_t
row_log_tmpfile(
row_log_t* log)
{
DBUG_ENTER("row_log_tmpfile");
if (log->fd < 0) {
if (log->fd == OS_FILE_CLOSED) {
log->fd = row_merge_file_create_low(log->path);
DBUG_EXECUTE_IF("row_log_tmpfile_fail",
if (log->fd > 0)
if (log->fd != OS_FILE_CLOSED)
row_merge_file_destroy_low(log->fd);
log->fd = -1;);
if (log->fd >= 0) {
log->fd = OS_FILE_CLOSED;);
if (log->fd != OS_FILE_CLOSED) {
MONITOR_ATOMIC_INC(MONITOR_ALTER_TABLE_LOG_FILES);
}
}
......@@ -392,7 +392,7 @@ row_log_online_op(
UNIV_MEM_ASSERT_RW(buf, srv_sort_buf_size);
if (row_log_tmpfile(log) < 0) {
if (row_log_tmpfile(log) == OS_FILE_CLOSED) {
log->error = DB_OUT_OF_MEMORY;
goto err_exit;
}
......@@ -413,7 +413,7 @@ row_log_online_op(
}
log->tail.blocks++;
if (!os_file_write_int_fd(
if (!os_file_write(
request,
"(modification log)",
log->fd,
......@@ -528,7 +528,7 @@ row_log_table_close_func(
UNIV_MEM_ASSERT_RW(buf, srv_sort_buf_size);
if (row_log_tmpfile(log) < 0) {
if (row_log_tmpfile(log) == OS_FILE_CLOSED) {
log->error = DB_OUT_OF_MEMORY;
goto err_exit;
}
......@@ -549,7 +549,7 @@ row_log_table_close_func(
}
log->tail.blocks++;
if (!os_file_write_int_fd(
if (!os_file_write(
request,
"(modification log)",
log->fd,
......@@ -2865,9 +2865,9 @@ row_log_table_apply_ops(
IORequest request(IORequest::READ);
byte* buf = index->online_log->head.block;
if (!os_file_read_no_error_handling_int_fd(
if (!os_file_read_no_error_handling(
request, index->online_log->fd,
buf, ofs, srv_sort_buf_size)) {
buf, ofs, srv_sort_buf_size, 0)) {
ib::error()
<< "Unable to read temporary file"
" for table " << index->table->name;
......@@ -3173,7 +3173,7 @@ row_log_allocate(
DBUG_RETURN(false);
}
log->fd = -1;
log->fd = OS_FILE_CLOSED;
mutex_create(LATCH_ID_INDEX_ONLINE_LOG, &log->mutex);
log->blobs = NULL;
......@@ -3732,9 +3732,9 @@ row_log_apply_ops(
byte* buf = index->online_log->head.block;
if (!os_file_read_no_error_handling_int_fd(
if (!os_file_read_no_error_handling(
request, index->online_log->fd,
buf, ofs, srv_sort_buf_size)) {
buf, ofs, srv_sort_buf_size, 0)) {
ib::error()
<< "Unable to read temporary file"
" for index " << index->name;
......
This diff is collapsed.
......@@ -756,7 +756,7 @@ dberr_t
srv_check_undo_redo_logs_exists()
{
bool ret;
os_file_t fh;
pfs_os_file_t fh;
char name[OS_FILE_MAX_PATH];
/* Check if any undo tablespaces exist */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment