summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_global.h9
-rw-r--r--include/my_sys.h1
-rw-r--r--mysys/my_create.c5
-rw-r--r--mysys/my_open.c184
-rw-r--r--sql/log.cc62
-rw-r--r--sql/sql_class.h6
-rw-r--r--sql/sql_repl.cc39
7 files changed, 207 insertions, 99 deletions
diff --git a/include/my_global.h b/include/my_global.h
index b32a8fe6baa..33cdfa2d03c 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -553,6 +553,15 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define O_NOFOLLOW 0
#endif
+/* additional file share flags for win32 */
+#ifdef __WIN__
+#define _SH_DENYRWD 0x110 /* deny read/write mode & delete */
+#define _SH_DENYWRD 0x120 /* deny write mode & delete */
+#define _SH_DENYRDD 0x130 /* deny read mode & delete */
+#define _SH_DENYDEL 0x140 /* deny delete only */
+#endif /* __WIN__ */
+
+
/* #define USE_RECORD_LOCK */
/* Unsigned types supported by the compiler */
diff --git a/include/my_sys.h b/include/my_sys.h
index 76031806b82..44fe383bf4f 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -601,6 +601,7 @@ extern char *_my_strdup_with_length(const byte *from, uint length,
#ifdef __WIN__
extern int my_access(const char *path, int amode);
+extern File my_sopen(const char *path, int oflag, int shflag, int pmode);
#else
#define my_access access
#endif
diff --git a/mysys/my_create.c b/mysys/my_create.c
index 5fa97a9ca78..a85417c7701 100644
--- a/mysys/my_create.c
+++ b/mysys/my_create.c
@@ -47,13 +47,16 @@ File my_create(const char *FileName, int CreateFlags, int access_flags,
#elif defined(VMS)
fd = open((my_string) FileName, access_flags | O_CREAT, 0,
"ctx=stm","ctx=bin");
-#elif defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2)
+#elif defined(MSDOS) || defined(__EMX__) || defined(OS2)
if (access_flags & O_SHARE)
fd = sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY,
SH_DENYNO, MY_S_IREAD | MY_S_IWRITE);
else
fd = open((my_string) FileName, access_flags | O_CREAT | O_BINARY,
MY_S_IREAD | MY_S_IWRITE);
+#elif defined(__WIN__)
+ fd= my_sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY,
+ SH_DENYNO, MY_S_IREAD | MY_S_IWRITE);
#else
fd = open(FileName, access_flags);
#endif
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 69d63c49554..baca97450b7 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -56,12 +56,18 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
DBUG_RETURN(my_register_filename(-1, FileName, FILE_BY_OPEN,
EE_FILENOTFOUND, MyFlags));
}
+#ifndef __WIN__
if (Flags & O_SHARE)
fd = sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
MY_S_IREAD | MY_S_IWRITE);
else
fd = open((my_string) FileName, Flags | O_BINARY,
MY_S_IREAD | MY_S_IWRITE);
+#else
+ fd= my_sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
+ MY_S_IREAD | MY_S_IWRITE);
+#endif
+
#elif !defined(NO_OPEN_3)
fd = open(FileName, Flags, my_umask); /* Normal unix */
#else
@@ -167,3 +173,181 @@ File my_register_filename(File fd, const char *FileName, enum file_type
FileName, my_errno);
return(fd);
}
+
+#ifdef __WIN__
+
+extern void __cdecl _dosmaperr(unsigned long);
+
+/*
+ Open a file with sharing. Similar to _sopen() from libc, but allows managing
+ share delete on win32
+
+ SYNOPSIS
+ my_sopen()
+ path fully qualified file name
+ oflag operation flags
+ shflag share flag
+ pmode permission flags
+
+ RETURN VALUE
+ File descriptor of opened file if success
+ -1 and sets errno if fails.
+*/
+
+File my_sopen(const char *path, int oflag, int shflag, int pmode)
+{
+ int fh; /* handle of opened file */
+ int mask;
+ HANDLE osfh; /* OS handle of opened file */
+ DWORD fileaccess; /* OS file access (requested) */
+ DWORD fileshare; /* OS file sharing mode */
+ DWORD filecreate; /* OS method of opening/creating */
+ DWORD fileattrib; /* OS file attribute flags */
+ SECURITY_ATTRIBUTES SecurityAttributes;
+
+ SecurityAttributes.nLength= sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor= NULL;
+ SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
+
+ /*
+ * decode the access flags
+ */
+ switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
+ case _O_RDONLY: /* read access */
+ fileaccess= GENERIC_READ;
+ break;
+ case _O_WRONLY: /* write access */
+ fileaccess= GENERIC_WRITE;
+ break;
+ case _O_RDWR: /* read and write access */
+ fileaccess= GENERIC_READ | GENERIC_WRITE;
+ break;
+ default: /* error, bad oflag */
+ errno= EINVAL;
+ _doserrno= 0L; /* not an OS error */
+ return -1;
+ }
+
+ /*
+ * decode sharing flags
+ */
+ switch (shflag) {
+ case _SH_DENYRW: /* exclusive access except delete */
+ fileshare= FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYWR: /* share read and delete access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYRD: /* share write and delete access */
+ fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYNO: /* share read, write and delete access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYRWD: /* exclusive access */
+ fileshare= 0L;
+ break;
+ case _SH_DENYWRD: /* share read access */
+ fileshare= FILE_SHARE_READ;
+ break;
+ case _SH_DENYRDD: /* share write access */
+ fileshare= FILE_SHARE_WRITE;
+ break;
+ case _SH_DENYDEL: /* share read and write access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE;
+ break;
+ default: /* error, bad shflag */
+ errno= EINVAL;
+ _doserrno= 0L; /* not an OS error */
+ return -1;
+ }
+
+ /*
+ * decode open/create method flags
+ */
+ switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
+ case 0:
+ case _O_EXCL: // ignore EXCL w/o CREAT
+ filecreate= OPEN_EXISTING;
+ break;
+
+ case _O_CREAT:
+ filecreate= OPEN_ALWAYS;
+ break;
+
+ case _O_CREAT | _O_EXCL:
+ case _O_CREAT | _O_TRUNC | _O_EXCL:
+ filecreate= CREATE_NEW;
+ break;
+
+ case _O_TRUNC:
+ case _O_TRUNC | _O_EXCL: // ignore EXCL w/o CREAT
+ filecreate= TRUNCATE_EXISTING;
+ break;
+
+ case _O_CREAT | _O_TRUNC:
+ filecreate= CREATE_ALWAYS;
+ break;
+
+ default:
+ // this can't happen ... all cases are covered
+ errno= EINVAL;
+ _doserrno= 0L;
+ return -1;
+ }
+
+ /*
+ * decode file attribute flags if _O_CREAT was specified
+ */
+ fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */
+ if (oflag & _O_CREAT)
+ {
+ _umask((mask= _umask(0)));
+
+ if (!((pmode & ~mask) & _S_IWRITE))
+ fileattrib= FILE_ATTRIBUTE_READONLY;
+ }
+
+ /*
+ * Set temporary file (delete-on-close) attribute if requested.
+ */
+ if (oflag & _O_TEMPORARY)
+ {
+ fileattrib|= FILE_FLAG_DELETE_ON_CLOSE;
+ fileaccess|= DELETE;
+ }
+
+ /*
+ * Set temporary file (delay-flush-to-disk) attribute if requested.
+ */
+ if (oflag & _O_SHORT_LIVED)
+ fileattrib|= FILE_ATTRIBUTE_TEMPORARY;
+
+ /*
+ * Set sequential or random access attribute if requested.
+ */
+ if (oflag & _O_SEQUENTIAL)
+ fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN;
+ else if (oflag & _O_RANDOM)
+ fileattrib|= FILE_FLAG_RANDOM_ACCESS;
+
+ /*
+ * try to open/create the file
+ */
+ if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
+ filecreate, fileattrib, NULL)) == (HANDLE)0xffffffff)
+ {
+ /*
+ * OS call to open/create file failed! map the error, release
+ * the lock, and return -1. note that it's not necessary to
+ * call _free_osfhnd (it hasn't been used yet).
+ */
+ _dosmaperr(GetLastError()); /* map error */
+ return -1; /* return error to caller */
+ }
+
+ fh= _open_osfhandle((long)osfh, oflag & (_O_APPEND | _O_RDONLY | _O_TEXT));
+
+ return fh; /* return handle */
+}
+#endif /* __WIN__ */
diff --git a/sql/log.cc b/sql/log.cc
index 4b3d6698051..e42f1def27c 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -357,8 +357,7 @@ static int find_uniq_filename(char *name)
MYSQL_LOG::MYSQL_LOG()
:bytes_written(0), last_time(0), query_start(0), name(0),
prepared_xids(0), log_type(LOG_CLOSED), file_id(1), open_count(1),
- readers_count(0), reset_pending(FALSE), write_error(FALSE), inited(FALSE),
- need_start_event(TRUE),
+ write_error(FALSE), inited(FALSE), need_start_event(TRUE),
description_event_for_exec(0), description_event_for_queue(0)
{
/*
@@ -385,9 +384,7 @@ void MYSQL_LOG::cleanup()
delete description_event_for_exec;
(void) pthread_mutex_destroy(&LOCK_log);
(void) pthread_mutex_destroy(&LOCK_index);
- (void) pthread_mutex_destroy(&LOCK_readers);
(void) pthread_cond_destroy(&update_cond);
- (void) pthread_cond_destroy(&reset_cond);
}
DBUG_VOID_RETURN;
}
@@ -432,9 +429,7 @@ void MYSQL_LOG::init_pthread_objects()
inited= 1;
(void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_readers, MY_MUTEX_INIT_SLOW);
(void) pthread_cond_init(&update_cond, 0);
- (void) pthread_cond_init(&reset_cond, 0);
}
const char *MYSQL_LOG::generate_name(const char *log_name,
@@ -938,12 +933,6 @@ bool MYSQL_LOG::reset_logs(THD* thd)
pthread_mutex_lock(&LOCK_log);
pthread_mutex_lock(&LOCK_index);
- /*
- we need one more lock to block attempts to open a log while
- we are waiting untill all log files will be closed
- */
- pthread_mutex_lock(&LOCK_readers);
-
/*
The following mutex is needed to ensure that no threads call
'delete thd' as we would then risk missing a 'rollback' from this
@@ -966,19 +955,6 @@ bool MYSQL_LOG::reset_logs(THD* thd)
goto err;
}
- reset_pending= TRUE;
- /*
- send update signal just in case so that all reader threads waiting
- for log update will leave wait condition
- */
- signal_update();
- /*
- if there are active readers wait until all of them will
- release opened files
- */
- while (readers_count)
- pthread_cond_wait(&reset_cond, &LOCK_log);
-
for (;;)
{
my_delete(linfo.log_file_name, MYF(MY_WME));
@@ -997,10 +973,7 @@ bool MYSQL_LOG::reset_logs(THD* thd)
my_free((gptr) save_name, MYF(0));
err:
- reset_pending= FALSE;
-
(void) pthread_mutex_unlock(&LOCK_thread_count);
- pthread_mutex_unlock(&LOCK_readers);
pthread_mutex_unlock(&LOCK_index);
pthread_mutex_unlock(&LOCK_log);
DBUG_RETURN(error);
@@ -2073,12 +2046,6 @@ void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave)
{
const char *old_msg;
DBUG_ENTER("wait_for_update");
-
- if (reset_pending)
- {
- pthread_mutex_unlock(&LOCK_log);
- DBUG_VOID_RETURN;
- }
old_msg= thd->enter_cond(&update_cond, &LOCK_log,
is_slave ?
@@ -2330,33 +2297,6 @@ void MYSQL_LOG::signal_update()
DBUG_VOID_RETURN;
}
-void MYSQL_LOG::readers_addref()
-{
- /*
- There is no necessity for reference counting on *nix, since it allows to
- delete opened files, however it is more clean way to wait
- untill all files will be closed on *nix as well.
- */
- DBUG_ENTER("MYSQL_LOG::reader_addref");
- pthread_mutex_lock(&LOCK_log);
- pthread_mutex_lock(&LOCK_readers);
- readers_count++;
- pthread_mutex_unlock(&LOCK_readers);
- pthread_mutex_unlock(&LOCK_log);
- DBUG_VOID_RETURN;
-}
-
-void MYSQL_LOG::readers_release()
-{
- DBUG_ENTER("MYSQL_LOG::reader_release");
- pthread_mutex_lock(&LOCK_log);
- readers_count--;
- if (!readers_count)
- pthread_cond_broadcast(&reset_cond);
- pthread_mutex_unlock(&LOCK_log);
- DBUG_VOID_RETURN;
-}
-
#ifdef __NT__
void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
uint length, int buffLen)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 2d1880a6d9d..eaa8291e697 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -189,11 +189,10 @@ class MYSQL_LOG: public TC_LOG
{
private:
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
- pthread_mutex_t LOCK_log, LOCK_index, LOCK_readers;
+ pthread_mutex_t LOCK_log, LOCK_index;
pthread_mutex_t LOCK_prep_xids;
pthread_cond_t COND_prep_xids;
pthread_cond_t update_cond;
- pthread_cond_t reset_cond;
ulonglong bytes_written;
time_t last_time,query_start;
IO_CACHE log_file;
@@ -335,9 +334,6 @@ public:
int purge_logs_before_date(time_t purge_time);
int purge_first_log(struct st_relay_log_info* rli, bool included);
bool reset_logs(THD* thd);
- inline bool is_reset_pending() { return reset_pending; }
- void readers_addref();
- void readers_release();
void close(uint exiting);
// iterating through the log index file
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index b5865fa8816..cd293fc21c7 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -372,11 +372,6 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
goto err;
}
- /*
- Call readers_addref before opening log to track count
- of binlog readers
- */
- mysql_bin_log.readers_addref();
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0)
{
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
@@ -574,8 +569,7 @@ impossible position";
goto err;
if (!(flags & BINLOG_DUMP_NON_BLOCK) &&
- mysql_bin_log.is_active(log_file_name) &&
- !mysql_bin_log.is_reset_pending())
+ mysql_bin_log.is_active(log_file_name))
{
/*
Block until there is more data in the log
@@ -688,13 +682,7 @@ impossible position";
else
{
bool loop_breaker = 0;
- // need this to break out of the for loop from switch
-
- // if we are going to switch log file anyway, close current log first
- end_io_cache(&log);
- (void) my_close(file, MYF(MY_WME));
- // decrease reference count of binlog readers
- mysql_bin_log.readers_release();
+ /* need this to break out of the for loop from switch */
thd->proc_info = "Finished reading one binlog; switching to next binlog";
switch (mysql_bin_log.find_next_log(&linfo, 1)) {
@@ -704,25 +692,16 @@ impossible position";
case 0:
break;
default:
- // need following call to do release on err label
- mysql_bin_log.readers_addref();
errmsg = "could not find next log";
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
- if (loop_breaker)
- {
- // need following call to do release on end label
- mysql_bin_log.readers_addref();
- break;
- }
-
- /*
- Call readers_addref before opening log to track count
- of binlog readers
- */
- mysql_bin_log.readers_addref();
+ if (loop_breaker)
+ break;
+
+ end_io_cache(&log);
+ (void) my_close(file, MYF(MY_WME));
/*
Call fake_rotate_event() in case the previous log (the one which
@@ -755,8 +734,6 @@ end:
end_io_cache(&log);
(void)my_close(file, MYF(MY_WME));
- // decrease reference count of binlog readers
- mysql_bin_log.readers_release();
send_eof(thd);
thd->proc_info = "Waiting to finalize termination";
@@ -783,8 +760,6 @@ err:
pthread_mutex_unlock(&LOCK_thread_count);
if (file >= 0)
(void) my_close(file, MYF(MY_WME));
- // decrease reference count of binlog readers
- mysql_bin_log.readers_release();
my_message(my_errno, errmsg, MYF(0));
DBUG_VOID_RETURN;