Commit 303cae4c authored by unknown's avatar unknown
Browse files

Fixes bug #13377. my_open() & my_create() functions changed to use

my_sopen() on win32 which allows to use FILE_SHARE_DELETE flag to 
allow deleting opened files. my_sopen() implementation is added to
support this functionality.


include/my_global.h:
  Fixes bug #13377. Added number of constants for share delete file
  open option.
include/my_sys.h:
  Fixes bug #13377. Added my_sopen function.
mysys/my_create.c:
  Fixes bug #13377. my_create() function changed to use my_sopen() and which allows
  to use FILE_SHARE_DELETE flag on win32, which helps in deleting opened files.
mysys/my_open.c:
  Fixes bug #13377. my_open() function changed to use my_sopen() on win32
  which allows to use FILE_SHARE_DELETE flag to allow deleting opened files.
sql/log.cc:
  Fixes bug #13377. Additional patch - remove reference counting for
  opened binlog files, introduced in initial patch of #13377.
sql/sql_class.h:
  Fixes bug #13377. Additional patch - remove reference counting for
  opened binlog files, introduced in initial patch of #13377.
sql/sql_repl.cc:
  Fixes bug #13377. Additional patch - remove reference counting for
  opened binlog files, introduced in initial patch of #13377.
parent b10c7d60
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -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
+4 −1
Original line number Diff line number Diff line
@@ -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
+184 −0
Original line number Diff line number Diff line
@@ -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__ */
+1 −61
Original line number Diff line number Diff line
@@ -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);
@@ -2074,12 +2047,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 ?
                           "Has read all relay log; waiting for the slave I/O "
@@ -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)
Loading