diff options
-rw-r--r-- | include/my_global.h | 9 | ||||
-rw-r--r-- | include/my_sys.h | 1 | ||||
-rw-r--r-- | mysys/my_create.c | 5 | ||||
-rw-r--r-- | mysys/my_open.c | 184 | ||||
-rw-r--r-- | sql/log.cc | 62 | ||||
-rw-r--r-- | sql/sql_class.h | 6 | ||||
-rw-r--r-- | sql/sql_repl.cc | 39 |
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; |