summaryrefslogtreecommitdiff
path: root/storage/perfschema/pfs_instr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/perfschema/pfs_instr.cc')
-rw-r--r--storage/perfschema/pfs_instr.cc231
1 files changed, 166 insertions, 65 deletions
diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc
index 9507e2d2582..0c7b25a03de 100644
--- a/storage/perfschema/pfs_instr.cc
+++ b/storage/perfschema/pfs_instr.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2008, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -10,8 +10,8 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ along with this program; if not, write to the Free Software Foundation,
+ 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
/**
@file storage/perfschema/pfs_instr.cc
@@ -21,8 +21,8 @@
#include <string.h>
#include "my_global.h"
-#include "sql_priv.h"
#include "my_sys.h"
+#include "pfs.h"
#include "pfs_stat.h"
#include "pfs_instr.h"
#include "pfs_global.h"
@@ -411,6 +411,8 @@ void cleanup_instruments(void)
thread_instr_class_waits_array= NULL;
}
+extern "C"
+{
static uchar *filename_hash_get_key(const uchar *entry, size_t *length,
my_bool)
{
@@ -425,6 +427,7 @@ static uchar *filename_hash_get_key(const uchar *entry, size_t *length,
result= file->m_filename;
return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
}
+}
/**
Initialize the file name hash.
@@ -451,6 +454,75 @@ void cleanup_file_hash(void)
}
}
+void PFS_scan::init(uint random, uint max_size)
+{
+ m_pass= 0;
+
+ if (max_size == 0)
+ {
+ /* Degenerated case, no buffer */
+ m_pass_max= 0;
+ return;
+ }
+
+ DBUG_ASSERT(random < max_size);
+
+ if (PFS_MAX_ALLOC_RETRY < max_size)
+ {
+ /*
+ The buffer is big compared to PFS_MAX_ALLOC_RETRY,
+ scan it only partially.
+ */
+ if (random + PFS_MAX_ALLOC_RETRY < max_size)
+ {
+ /*
+ Pass 1: [random, random + PFS_MAX_ALLOC_RETRY - 1]
+ Pass 2: not used.
+ */
+ m_pass_max= 1;
+ m_first[0]= random;
+ m_last[0]= random + PFS_MAX_ALLOC_RETRY;
+ m_first[1]= 0;
+ m_last[1]= 0;
+ }
+ else
+ {
+ /*
+ Pass 1: [random, max_size - 1]
+ Pass 2: [0, ...]
+ The combined length of pass 1 and 2 is PFS_MAX_ALLOC_RETRY.
+ */
+ m_pass_max= 2;
+ m_first[0]= random;
+ m_last[0]= max_size;
+ m_first[1]= 0;
+ m_last[1]= PFS_MAX_ALLOC_RETRY - (max_size - random);
+ }
+ }
+ else
+ {
+ /*
+ The buffer is small compared to PFS_MAX_ALLOC_RETRY,
+ scan it in full in two passes.
+ Pass 1: [random, max_size - 1]
+ Pass 2: [0, random - 1]
+ */
+ m_pass_max= 2;
+ m_first[0]= random;
+ m_last[0]= max_size;
+ m_first[1]= 0;
+ m_last[1]= random;
+ }
+
+ DBUG_ASSERT(m_first[0] < max_size);
+ DBUG_ASSERT(m_first[1] < max_size);
+ DBUG_ASSERT(m_last[1] <= max_size);
+ DBUG_ASSERT(m_last[1] <= max_size);
+ /* The combined length of all passes should not exceed PFS_MAX_ALLOC_RETRY. */
+ DBUG_ASSERT((m_last[0] - m_first[0]) +
+ (m_last[1] - m_first[1]) <= PFS_MAX_ALLOC_RETRY);
+}
+
/**
Create instrumentation for a mutex instance.
@param klass the mutex class
@@ -459,17 +531,15 @@ void cleanup_file_hash(void)
*/
PFS_mutex* create_mutex(PFS_mutex_class *klass, const void *identity)
{
- int pass;
- uint i= randomized_index(identity, mutex_max);
+ PFS_scan scan;
+ uint random= randomized_index(identity, mutex_max);
- /*
- Pass 1: [random, mutex_max - 1]
- Pass 2: [0, mutex_max - 1]
- */
- for (pass= 1; pass <= 2; i=0, pass++)
+ for (scan.init(random, mutex_max);
+ scan.has_pass();
+ scan.next_pass())
{
- PFS_mutex *pfs= mutex_array + i;
- PFS_mutex *pfs_last= mutex_array + mutex_max;
+ PFS_mutex *pfs= mutex_array + scan.first();
+ PFS_mutex *pfs_last= mutex_array + scan.last();
for ( ; pfs < pfs_last; pfs++)
{
if (pfs->m_lock.is_free())
@@ -517,17 +587,15 @@ void destroy_mutex(PFS_mutex *pfs)
*/
PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void *identity)
{
- int pass;
- uint i= randomized_index(identity, rwlock_max);
+ PFS_scan scan;
+ uint random= randomized_index(identity, rwlock_max);
- /*
- Pass 1: [random, rwlock_max - 1]
- Pass 2: [0, rwlock_max - 1]
- */
- for (pass= 1; pass <= 2; i=0, pass++)
+ for (scan.init(random, rwlock_max);
+ scan.has_pass();
+ scan.next_pass())
{
- PFS_rwlock *pfs= rwlock_array + i;
- PFS_rwlock *pfs_last= rwlock_array + rwlock_max;
+ PFS_rwlock *pfs= rwlock_array + scan.first();
+ PFS_rwlock *pfs_last= rwlock_array + scan.last();
for ( ; pfs < pfs_last; pfs++)
{
if (pfs->m_lock.is_free())
@@ -581,17 +649,15 @@ void destroy_rwlock(PFS_rwlock *pfs)
*/
PFS_cond* create_cond(PFS_cond_class *klass, const void *identity)
{
- int pass;
- uint i= randomized_index(identity, cond_max);
+ PFS_scan scan;
+ uint random= randomized_index(identity, cond_max);
- /*
- Pass 1: [random, cond_max - 1]
- Pass 2: [0, cond_max - 1]
- */
- for (pass= 1; pass <= 2; i=0, pass++)
+ for (scan.init(random, cond_max);
+ scan.has_pass();
+ scan.next_pass())
{
- PFS_cond *pfs= cond_array + i;
- PFS_cond *pfs_last= cond_array + cond_max;
+ PFS_cond *pfs= cond_array + scan.first();
+ PFS_cond *pfs_last= cond_array + scan.last();
for ( ; pfs < pfs_last; pfs++)
{
if (pfs->m_lock.is_free())
@@ -639,17 +705,15 @@ void destroy_cond(PFS_cond *pfs)
PFS_thread* create_thread(PFS_thread_class *klass, const void *identity,
ulong thread_id)
{
- int pass;
- uint i= randomized_index(identity, thread_max);
+ PFS_scan scan;
+ uint random= randomized_index(identity, thread_max);
- /*
- Pass 1: [random, thread_max - 1]
- Pass 2: [0, thread_max - 1]
- */
- for (pass= 1; pass <= 2; i=0, pass++)
+ for (scan.init(random, thread_max);
+ scan.has_pass();
+ scan.next_pass())
{
- PFS_thread *pfs= thread_array + i;
- PFS_thread *pfs_last= thread_array + thread_max;
+ PFS_thread *pfs= thread_array + scan.first();
+ PFS_thread *pfs_last= thread_array + scan.last();
for ( ; pfs < pfs_last; pfs++)
{
if (pfs->m_lock.is_free())
@@ -733,7 +797,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
const char *filename, uint len)
{
PFS_file *pfs;
- int pass;
+ PFS_scan scan;
if (! filename_hash_inited)
{
@@ -765,7 +829,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
- it fits into pfs->m_filename
- it is safe to use mysys apis to normalize the file name.
*/
- memcpy(safe_buffer, filename, FN_REFLEN - 2);
+ memcpy(safe_buffer, filename, FN_REFLEN - 1);
safe_buffer[FN_REFLEN - 1]= 0;
safe_filename= safe_buffer;
}
@@ -776,16 +840,58 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
Normalize the file name to avoid duplicates when using aliases:
- absolute or relative paths
- symbolic links
+ Names are resolved as follows:
+ - /real/path/to/real_file ==> same
+ - /path/with/link/to/real_file ==> /real/path/to/real_file
+ - real_file ==> /real/path/to/real_file
+ - ./real_file ==> /real/path/to/real_file
+ - /real/path/to/sym_link ==> same
+ - /path/with/link/to/sym_link ==> /real/path/to/sym_link
+ - sym_link ==> /real/path/to/sym_link
+ - ./sym_link ==> /real/path/to/sym_link
+ When the last component of a file is a symbolic link,
+ the last component is *not* resolved, so that all file io
+ operations on a link (create, read, write, delete) are counted
+ against the link itself, not the target file.
+ Resolving the name would lead to create counted against the link,
+ and read/write/delete counted against the target, leading to
+ incoherent results and instrumentation leaks.
+ Also note that, when creating files, this name resolution
+ works properly for files that do not exist (yet) on the file system.
*/
char buffer[FN_REFLEN];
+ char dirbuffer[FN_REFLEN];
+ size_t dirlen;
const char *normalized_filename;
int normalized_length;
- /*
- Ignore errors, the file may not exist.
- my_realpath always provide a best effort result in buffer.
- */
- (void) my_realpath(buffer, safe_filename, MYF(0));
+ dirlen= dirname_length(safe_filename);
+ if (dirlen == 0)
+ {
+ dirbuffer[0]= FN_CURLIB;
+ dirbuffer[1]= FN_LIBCHAR;
+ dirbuffer[2]= '\0';
+ }
+ else
+ {
+ memcpy(dirbuffer, safe_filename, dirlen);
+ dirbuffer[dirlen]= '\0';
+ }
+
+ if (my_realpath(buffer, dirbuffer, MYF(0)) != 0)
+ {
+ file_lost++;
+ return NULL;
+ }
+
+ /* Append the unresolved file name to the resolved path */
+ char *ptr= buffer + strlen(buffer);
+ char *buf_end= &buffer[sizeof(buffer)-1];
+ if (buf_end > ptr)
+ *ptr++= FN_LIBCHAR;
+ if (buf_end > ptr)
+ strncpy(ptr, safe_filename + dirlen, buf_end - ptr);
+ *buf_end= '\0';
normalized_filename= buffer;
normalized_length= strlen(normalized_filename);
@@ -806,17 +912,14 @@ search:
}
/* filename is not constant, just using it for noise on create */
- uint i= randomized_index(filename, file_max);
+ uint random= randomized_index(filename, file_max);
- /*
- Pass 1: [random, file_max - 1]
- Pass 2: [0, file_max - 1]
- */
- for (pass= 1; pass <= 2; i=0, pass++)
+ for (scan.init(random, file_max);
+ scan.has_pass();
+ scan.next_pass())
{
- pfs= file_array + i;
- PFS_file *pfs_last= file_array + file_max;
-
+ pfs= file_array + scan.first();
+ PFS_file *pfs_last= file_array + scan.last();
for ( ; pfs < pfs_last; pfs++)
{
if (pfs->m_lock.is_free())
@@ -901,17 +1004,15 @@ void destroy_file(PFS_thread *thread, PFS_file *pfs)
*/
PFS_table* create_table(PFS_table_share *share, const void *identity)
{
- int pass;
- uint i= randomized_index(identity, table_max);
+ PFS_scan scan;
+ uint random= randomized_index(identity, table_max);
- /*
- Pass 1: [random, table_max - 1]
- Pass 2: [0, table_max - 1]
- */
- for (pass= 1; pass <= 2; i=0, pass++)
+ for (scan.init(random, table_max);
+ scan.has_pass();
+ scan.next_pass())
{
- PFS_table *pfs= table_array + i;
- PFS_table *pfs_last= table_array + table_max;
+ PFS_table *pfs= table_array + scan.first();
+ PFS_table *pfs_last= table_array + scan.last();
for ( ; pfs < pfs_last; pfs++)
{
if (pfs->m_lock.is_free())