mariadb/storage/perfschema/unittest/pfs-t.cc
Marc Alff ec41287630 Bug#55087 Performance schema: optimization of the instrumentation interface
This change is for performance optimization.

Fixed the performance schema instrumentation interface as follows:
- simplified mysql_unlock_mutex()
- simplified mysql_unlock_rwlock()
- simplified mysql_cond_signal()
- simplified mysql_cond_broadcast()

Changed the get_thread_XXX_locker apis to have one extra parameter,
to provide memory to the instrumentation implementation.
This API change allows to use memory provided by the caller,
to avoid having to use thread local storage.
Using this extra parameter will be done in a separate fix,
this change is for the interface only.

Adjusted all the code and unit tests accordingly.
2010-07-09 17:00:24 -06:00

1222 lines
35 KiB
C++

/* Copyright (C) 2009 Sun Microsystems, Inc
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
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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 */
#include <my_pthread.h>
#include <sql_priv.h>
#include <my_global.h>
#include <pfs_server.h>
#include <pfs_instr_class.h>
#include <pfs_instr.h>
#include <pfs_global.h>
#include <tap.h>
#include <string.h>
#include <memory.h>
#include "stub_print_error.h"
/* test helpers, to simulate the setup */
void setup_thread(PSI_thread *t, bool enabled)
{
PFS_thread *t2= (PFS_thread*) t;
t2->m_enabled= enabled;
}
/* test helpers, to inspect data */
PFS_file* lookup_file_by_name(const char* name)
{
uint i;
PFS_file *pfs;
uint len= strlen(name);
size_t dirlen;
const char *filename;
uint filename_length;;
for (i= 0; i < file_max; i++)
{
pfs= & file_array[i];
if (pfs->m_lock.is_populated())
{
/*
When a file "foo" is instrumented, the name is normalized
to "/path/to/current/directory/foo", so we remove the
directory name here to find it back.
*/
dirlen= dirname_length(pfs->m_filename);
filename= pfs->m_filename + dirlen;
filename_length= pfs->m_filename_length - dirlen;
if ((len == filename_length) &&
(strncmp(name, filename, filename_length) == 0))
return pfs;
}
}
return NULL;
}
/* tests */
void test_bootstrap()
{
void *psi;
void *psi_2;
PSI_bootstrap *boot;
PFS_global_param param;
diag("test_bootstrap");
param.m_enabled= true;
param.m_mutex_class_sizing= 0;
param.m_rwlock_class_sizing= 0;
param.m_cond_class_sizing= 0;
param.m_thread_class_sizing= 0;
param.m_table_share_sizing= 0;
param.m_file_class_sizing= 0;
param.m_mutex_sizing= 0;
param.m_rwlock_sizing= 0;
param.m_cond_sizing= 0;
param.m_thread_sizing= 0;
param.m_table_sizing= 0;
param.m_file_sizing= 0;
param.m_file_handle_sizing= 0;
param.m_events_waits_history_sizing= 0;
param.m_events_waits_history_long_sizing= 0;
boot= initialize_performance_schema(& param);
ok(boot != NULL, "boot");
ok(boot->get_interface != NULL, "boot->get_interface");
psi= boot->get_interface(0);
ok(psi == NULL, "no version 0");
psi= boot->get_interface(PSI_VERSION_1);
ok(psi != NULL, "version 1");
psi_2= boot->get_interface(PSI_VERSION_2);
ok(psi_2 == NULL, "version 2");
shutdown_performance_schema();
}
/*
Not a test, helper for testing pfs.cc
*/
PSI * load_perfschema()
{
void *psi;
PSI_bootstrap *boot;
PFS_global_param param;
param.m_enabled= true;
param.m_mutex_class_sizing= 10;
param.m_rwlock_class_sizing= 10;
param.m_cond_class_sizing= 10;
param.m_thread_class_sizing= 10;
param.m_table_share_sizing= 10;
param.m_file_class_sizing= 10;
param.m_mutex_sizing= 10;
param.m_rwlock_sizing= 10;
param.m_cond_sizing= 10;
param.m_thread_sizing= 10;
param.m_table_sizing= 10;
param.m_file_sizing= 10;
param.m_file_handle_sizing= 50;
param.m_events_waits_history_sizing= 10;
param.m_events_waits_history_long_sizing= 10;
/* test_bootstrap() covered this, assuming it just works */
boot= initialize_performance_schema(& param);
psi= boot->get_interface(PSI_VERSION_1);
return (PSI*) psi;
}
void test_bad_registration()
{
PSI *psi;
diag("test_bad_registration");
psi= load_perfschema();
/*
Test that length('wait/synch/mutex/' (17) + category + '/' (1)) < 32
--> category can be up to 13 chars for a mutex.
*/
PSI_mutex_key dummy_mutex_key= 9999;
PSI_mutex_info bad_mutex_1[]=
{
{ & dummy_mutex_key, "X", 0}
};
psi->register_mutex("/", bad_mutex_1, 1);
ok(dummy_mutex_key == 0, "zero key");
dummy_mutex_key= 9999;
psi->register_mutex("a/", bad_mutex_1, 1);
ok(dummy_mutex_key == 0, "zero key");
dummy_mutex_key= 9999;
psi->register_mutex("/b", bad_mutex_1, 1);
ok(dummy_mutex_key == 0, "zero key");
dummy_mutex_key= 9999;
psi->register_mutex("a/b", bad_mutex_1, 1);
ok(dummy_mutex_key == 0, "zero key");
dummy_mutex_key= 9999;
psi->register_mutex("12345678901234", bad_mutex_1, 1);
ok(dummy_mutex_key == 0, "zero key");
dummy_mutex_key= 9999;
psi->register_mutex("1234567890123", bad_mutex_1, 1);
ok(dummy_mutex_key == 1, "assigned key");
/*
Test that length('wait/synch/mutex/' (17) + category + '/' (1) + name) <= 128
--> category + name can be up to 110 chars for a mutex.
*/
dummy_mutex_key= 9999;
PSI_mutex_info bad_mutex_2[]=
{
{ & dummy_mutex_key,
/* 110 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"1234567890",
0}
};
psi->register_mutex("X", bad_mutex_2, 1);
ok(dummy_mutex_key == 0, "zero key");
dummy_mutex_key= 9999;
PSI_mutex_info bad_mutex_3[]=
{
{ & dummy_mutex_key,
/* 109 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"123456789",
0}
};
psi->register_mutex("XX", bad_mutex_3, 1);
ok(dummy_mutex_key == 0, "zero key");
psi->register_mutex("X", bad_mutex_3, 1);
ok(dummy_mutex_key == 2, "assigned key");
/*
Test that length('wait/synch/rwlock/' (18) + category + '/' (1)) < 32
--> category can be up to 12 chars for a rwlock.
*/
PSI_rwlock_key dummy_rwlock_key= 9999;
PSI_rwlock_info bad_rwlock_1[]=
{
{ & dummy_rwlock_key, "X", 0}
};
psi->register_rwlock("/", bad_rwlock_1, 1);
ok(dummy_rwlock_key == 0, "zero key");
dummy_rwlock_key= 9999;
psi->register_rwlock("a/", bad_rwlock_1, 1);
ok(dummy_rwlock_key == 0, "zero key");
dummy_rwlock_key= 9999;
psi->register_rwlock("/b", bad_rwlock_1, 1);
ok(dummy_rwlock_key == 0, "zero key");
dummy_rwlock_key= 9999;
psi->register_rwlock("a/b", bad_rwlock_1, 1);
ok(dummy_rwlock_key == 0, "zero key");
dummy_rwlock_key= 9999;
psi->register_rwlock("1234567890123", bad_rwlock_1, 1);
ok(dummy_rwlock_key == 0, "zero key");
dummy_rwlock_key= 9999;
psi->register_rwlock("123456789012", bad_rwlock_1, 1);
ok(dummy_rwlock_key == 1, "assigned key");
/*
Test that length('wait/synch/rwlock/' (18) + category + '/' (1) + name) <= 128
--> category + name can be up to 109 chars for a rwlock.
*/
dummy_rwlock_key= 9999;
PSI_rwlock_info bad_rwlock_2[]=
{
{ & dummy_rwlock_key,
/* 109 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"123456789",
0}
};
psi->register_rwlock("X", bad_rwlock_2, 1);
ok(dummy_rwlock_key == 0, "zero key");
dummy_rwlock_key= 9999;
PSI_rwlock_info bad_rwlock_3[]=
{
{ & dummy_rwlock_key,
/* 108 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"12345678",
0}
};
psi->register_rwlock("XX", bad_rwlock_3, 1);
ok(dummy_rwlock_key == 0, "zero key");
psi->register_rwlock("X", bad_rwlock_3, 1);
ok(dummy_rwlock_key == 2, "assigned key");
/*
Test that length('wait/synch/cond/' (16) + category + '/' (1)) < 32
--> category can be up to 14 chars for a cond.
*/
PSI_cond_key dummy_cond_key= 9999;
PSI_cond_info bad_cond_1[]=
{
{ & dummy_cond_key, "X", 0}
};
psi->register_cond("/", bad_cond_1, 1);
ok(dummy_cond_key == 0, "zero key");
dummy_cond_key= 9999;
psi->register_cond("a/", bad_cond_1, 1);
ok(dummy_cond_key == 0, "zero key");
dummy_cond_key= 9999;
psi->register_cond("/b", bad_cond_1, 1);
ok(dummy_cond_key == 0, "zero key");
dummy_cond_key= 9999;
psi->register_cond("a/b", bad_cond_1, 1);
ok(dummy_cond_key == 0, "zero key");
dummy_cond_key= 9999;
psi->register_cond("123456789012345", bad_cond_1, 1);
ok(dummy_cond_key == 0, "zero key");
dummy_cond_key= 9999;
psi->register_cond("12345678901234", bad_cond_1, 1);
ok(dummy_cond_key == 1, "assigned key");
/*
Test that length('wait/synch/cond/' (16) + category + '/' (1) + name) <= 128
--> category + name can be up to 111 chars for a cond.
*/
dummy_cond_key= 9999;
PSI_cond_info bad_cond_2[]=
{
{ & dummy_cond_key,
/* 111 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"12345678901",
0}
};
psi->register_cond("X", bad_cond_2, 1);
ok(dummy_cond_key == 0, "zero key");
dummy_cond_key= 9999;
PSI_cond_info bad_cond_3[]=
{
{ & dummy_cond_key,
/* 110 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"1234567890",
0}
};
psi->register_cond("XX", bad_cond_3, 1);
ok(dummy_cond_key == 0, "zero key");
psi->register_cond("X", bad_cond_3, 1);
ok(dummy_cond_key == 2, "assigned key");
/*
Test that length('thread/' (7) + category + '/' (1)) < 32
--> category can be up to 23 chars for a thread.
*/
PSI_thread_key dummy_thread_key= 9999;
PSI_thread_info bad_thread_1[]=
{
{ & dummy_thread_key, "X", 0}
};
psi->register_thread("/", bad_thread_1, 1);
ok(dummy_thread_key == 0, "zero key");
dummy_thread_key= 9999;
psi->register_thread("a/", bad_thread_1, 1);
ok(dummy_thread_key == 0, "zero key");
dummy_thread_key= 9999;
psi->register_thread("/b", bad_thread_1, 1);
ok(dummy_thread_key == 0, "zero key");
dummy_thread_key= 9999;
psi->register_thread("a/b", bad_thread_1, 1);
ok(dummy_thread_key == 0, "zero key");
dummy_thread_key= 9999;
psi->register_thread("123456789012345678901234", bad_thread_1, 1);
ok(dummy_thread_key == 0, "zero key");
dummy_thread_key= 9999;
psi->register_thread("12345678901234567890123", bad_thread_1, 1);
ok(dummy_thread_key == 1, "assigned key");
/*
Test that length('thread/' (7) + category + '/' (1) + name) <= 128
--> category + name can be up to 120 chars for a thread.
*/
dummy_thread_key= 9999;
PSI_thread_info bad_thread_2[]=
{
{ & dummy_thread_key,
/* 120 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"12345678901234567890",
0}
};
psi->register_thread("X", bad_thread_2, 1);
ok(dummy_thread_key == 0, "zero key");
dummy_thread_key= 9999;
PSI_thread_info bad_thread_3[]=
{
{ & dummy_thread_key,
/* 119 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"1234567890123456789",
0}
};
psi->register_thread("XX", bad_thread_3, 1);
ok(dummy_thread_key == 0, "zero key");
psi->register_thread("X", bad_thread_3, 1);
ok(dummy_thread_key == 2, "assigned key");
/*
Test that length('wait/io/file/' (13) + category + '/' (1)) < 32
--> category can be up to 17 chars for a file.
*/
PSI_file_key dummy_file_key= 9999;
PSI_file_info bad_file_1[]=
{
{ & dummy_file_key, "X", 0}
};
psi->register_file("/", bad_file_1, 1);
ok(dummy_file_key == 0, "zero key");
dummy_file_key= 9999;
psi->register_file("a/", bad_file_1, 1);
ok(dummy_file_key == 0, "zero key");
dummy_file_key= 9999;
psi->register_file("/b", bad_file_1, 1);
ok(dummy_file_key == 0, "zero key");
dummy_file_key= 9999;
psi->register_file("a/b", bad_file_1, 1);
ok(dummy_file_key == 0, "zero key");
dummy_file_key= 9999;
psi->register_file("123456789012345678", bad_file_1, 1);
ok(dummy_file_key == 0, "zero key");
dummy_file_key= 9999;
psi->register_file("12345678901234567", bad_file_1, 1);
ok(dummy_file_key == 1, "assigned key");
/*
Test that length('wait/io/file/' (13) + category + '/' (1) + name) <= 128
--> category + name can be up to 114 chars for a file.
*/
dummy_file_key= 9999;
PSI_file_info bad_file_2[]=
{
{ & dummy_file_key,
/* 114 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"12345678901234",
0}
};
psi->register_file("X", bad_file_2, 1);
ok(dummy_file_key == 0, "zero key");
dummy_file_key= 9999;
PSI_file_info bad_file_3[]=
{
{ & dummy_file_key,
/* 113 chars name */
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"1234567890123",
0}
};
psi->register_file("XX", bad_file_3, 1);
ok(dummy_file_key == 0, "zero key");
psi->register_file("X", bad_file_3, 1);
ok(dummy_file_key == 2, "assigned key");
shutdown_performance_schema();
}
void test_init_disabled()
{
PSI *psi;
diag("test_init_disabled");
psi= load_perfschema();
PSI_mutex_key mutex_key_A;
PSI_mutex_info all_mutex[]=
{
{ & mutex_key_A, "M-A", 0}
};
PSI_rwlock_key rwlock_key_A;
PSI_rwlock_info all_rwlock[]=
{
{ & rwlock_key_A, "RW-A", 0}
};
PSI_cond_key cond_key_A;
PSI_cond_info all_cond[]=
{
{ & cond_key_A, "C-A", 0}
};
PSI_file_key file_key_A;
PSI_file_info all_file[]=
{
{ & file_key_A, "F-A", 0}
};
PSI_thread_key thread_key_1;
PSI_thread_info all_thread[]=
{
{ & thread_key_1, "T-1", 0}
};
psi->register_mutex("test", all_mutex, 1);
psi->register_rwlock("test", all_rwlock, 1);
psi->register_cond("test", all_cond, 1);
psi->register_file("test", all_file, 1);
psi->register_thread("test", all_thread, 1);
PFS_mutex_class *mutex_class_A;
PFS_rwlock_class *rwlock_class_A;
PFS_cond_class *cond_class_A;
PFS_file_class *file_class_A;
PSI_mutex *mutex_A1;
PSI_rwlock *rwlock_A1;
PSI_cond *cond_A1;
PFS_file *file_A1;
PSI_thread *thread_1;
/* Preparation */
thread_1= psi->new_thread(thread_key_1, NULL, 0);
ok(thread_1 != NULL, "T-1");
psi->set_thread_id(thread_1, 1);
mutex_class_A= find_mutex_class(mutex_key_A);
ok(mutex_class_A != NULL, "mutex class A");
rwlock_class_A= find_rwlock_class(rwlock_key_A);
ok(rwlock_class_A != NULL, "rwlock class A");
cond_class_A= find_cond_class(cond_key_A);
ok(cond_class_A != NULL, "cond class A");
file_class_A= find_file_class(file_key_A);
ok(file_class_A != NULL, "file class A");
/* Pretend thread T-1 is running, and disabled */
/* ------------------------------------------- */
psi->set_thread(thread_1);
setup_thread(thread_1, false);
/* disabled M-A + disabled T-1: no instrumentation */
mutex_class_A->m_enabled= false;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
ok(mutex_A1 == NULL, "not instrumented");
/* enabled M-A + disabled T-1: no instrumentation */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
ok(mutex_A1 == NULL, "not instrumented");
/* broken key + disabled T-1: no instrumentation */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(0, NULL);
ok(mutex_A1 == NULL, "not instrumented");
mutex_A1= psi->init_mutex(99, NULL);
ok(mutex_A1 == NULL, "not instrumented");
/* disabled RW-A + disabled T-1: no instrumentation */
rwlock_class_A->m_enabled= false;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
/* enabled RW-A + disabled T-1: no instrumentation */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
/* broken key + disabled T-1: no instrumentation */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(0, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
rwlock_A1= psi->init_rwlock(99, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
/* disabled C-A + disabled T-1: no instrumentation */
cond_class_A->m_enabled= false;
cond_A1= psi->init_cond(cond_key_A, NULL);
ok(cond_A1 == NULL, "not instrumented");
/* enabled C-A + disabled T-1: no instrumentation */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(cond_key_A, NULL);
ok(cond_A1 == NULL, "not instrumented");
/* broken key + disabled T-1: no instrumentation */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(0, NULL);
ok(cond_A1 == NULL, "not instrumented");
cond_A1= psi->init_cond(99, NULL);
ok(cond_A1 == NULL, "not instrumented");
/* disabled F-A + disabled T-1: no instrumentation */
file_class_A->m_enabled= false;
psi->create_file(file_key_A, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
/* enabled F-A + disabled T-1: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(file_key_A, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
/* broken key + disabled T-1: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(0, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
psi->create_file(99, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
/* Pretend thread T-1 is enabled */
/* ----------------------------- */
setup_thread(thread_1, true);
/* disabled M-A + enabled T-1: no instrumentation */
mutex_class_A->m_enabled= false;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
ok(mutex_A1 == NULL, "not instrumented");
/* enabled M-A + enabled T-1: instrumentation */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
ok(mutex_A1 != NULL, "instrumented");
psi->destroy_mutex(mutex_A1);
/* broken key + enabled T-1: no instrumentation */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(0, NULL);
ok(mutex_A1 == NULL, "not instrumented");
mutex_A1= psi->init_mutex(99, NULL);
ok(mutex_A1 == NULL, "not instrumented");
/* disabled RW-A + enabled T-1: no instrumentation */
rwlock_class_A->m_enabled= false;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
/* enabled RW-A + enabled T-1: instrumentation */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
ok(rwlock_A1 != NULL, "instrumented");
psi->destroy_rwlock(rwlock_A1);
/* broken key + enabled T-1: no instrumentation */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(0, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
rwlock_A1= psi->init_rwlock(99, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
/* disabled C-A + enabled T-1: no instrumentation */
cond_class_A->m_enabled= false;
cond_A1= psi->init_cond(cond_key_A, NULL);
ok(cond_A1 == NULL, "not instrumented");
/* enabled C-A + enabled T-1: instrumentation */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(cond_key_A, NULL);
ok(cond_A1 != NULL, "instrumented");
psi->destroy_cond(cond_A1);
/* broken key + enabled T-1: no instrumentation */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(0, NULL);
ok(cond_A1 == NULL, "not instrumented");
cond_A1= psi->init_cond(99, NULL);
ok(cond_A1 == NULL, "not instrumented");
/* disabled F-A + enabled T-1: no instrumentation */
file_class_A->m_enabled= false;
psi->create_file(file_key_A, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
/* enabled F-A + open failed + enabled T-1: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(file_key_A, "foo", (File) -1);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
/* enabled F-A + out-of-descriptors + enabled T-1: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(file_key_A, "foo", (File) 65000);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
ok(file_handle_lost == 1, "lost a file handle");
file_handle_lost= 0;
/* enabled F-A + enabled T-1: instrumentation */
file_class_A->m_enabled= true;
psi->create_file(file_key_A, "foo-instrumented", (File) 12);
file_A1= lookup_file_by_name("foo-instrumented");
ok(file_A1 != NULL, "instrumented");
/* broken key + enabled T-1: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(0, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
psi->create_file(99, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
/* Pretend the running thread is not instrumented */
/* ---------------------------------------------- */
psi->delete_current_thread();
/* disabled M-A + unknown thread: no instrumentation */
mutex_class_A->m_enabled= false;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
ok(mutex_A1 == NULL, "not instrumented");
/* enabled M-A + unknown thread: no instrumentation */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
ok(mutex_A1 == NULL, "not instrumented");
/* broken key + unknown thread: no instrumentation */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(0, NULL);
ok(mutex_A1 == NULL, "not instrumented");
mutex_A1= psi->init_mutex(99, NULL);
ok(mutex_A1 == NULL, "not instrumented");
/* disabled RW-A + unknown thread: no instrumentation */
rwlock_class_A->m_enabled= false;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
/* enabled RW-A + unknown thread: no instrumentation */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
/* broken key + unknown thread: no instrumentation */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(0, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
rwlock_A1= psi->init_rwlock(99, NULL);
ok(rwlock_A1 == NULL, "not instrumented");
/* disabled C-A + unknown thread: no instrumentation */
cond_class_A->m_enabled= false;
cond_A1= psi->init_cond(cond_key_A, NULL);
ok(cond_A1 == NULL, "not instrumented");
/* enabled C-A + unknown thread: no instrumentation */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(cond_key_A, NULL);
ok(cond_A1 == NULL, "not instrumented");
/* broken key + unknown thread: no instrumentation */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(0, NULL);
ok(cond_A1 == NULL, "not instrumented");
cond_A1= psi->init_cond(99, NULL);
ok(cond_A1 == NULL, "not instrumented");
/* disabled F-A + unknown thread: no instrumentation */
file_class_A->m_enabled= false;
psi->create_file(file_key_A, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
/* enabled F-A + unknown thread: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(file_key_A, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
/* broken key + unknown thread: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(0, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
psi->create_file(99, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
ok(file_A1 == NULL, "not instrumented");
shutdown_performance_schema();
}
void test_locker_disabled()
{
PSI *psi;
diag("test_locker_disabled");
psi= load_perfschema();
PSI_mutex_key mutex_key_A;
PSI_mutex_info all_mutex[]=
{
{ & mutex_key_A, "M-A", 0}
};
PSI_rwlock_key rwlock_key_A;
PSI_rwlock_info all_rwlock[]=
{
{ & rwlock_key_A, "RW-A", 0}
};
PSI_cond_key cond_key_A;
PSI_cond_info all_cond[]=
{
{ & cond_key_A, "C-A", 0}
};
PSI_file_key file_key_A;
PSI_file_info all_file[]=
{
{ & file_key_A, "F-A", 0}
};
PSI_thread_key thread_key_1;
PSI_thread_info all_thread[]=
{
{ & thread_key_1, "T-1", 0}
};
psi->register_mutex("test", all_mutex, 1);
psi->register_rwlock("test", all_rwlock, 1);
psi->register_cond("test", all_cond, 1);
psi->register_file("test", all_file, 1);
psi->register_thread("test", all_thread, 1);
PFS_mutex_class *mutex_class_A;
PFS_rwlock_class *rwlock_class_A;
PFS_cond_class *cond_class_A;
PFS_file_class *file_class_A;
PSI_mutex *mutex_A1;
PSI_rwlock *rwlock_A1;
PSI_cond *cond_A1;
PSI_file *file_A1;
PSI_thread *thread_1;
/* Preparation */
thread_1= psi->new_thread(thread_key_1, NULL, 0);
ok(thread_1 != NULL, "T-1");
psi->set_thread_id(thread_1, 1);
mutex_class_A= find_mutex_class(mutex_key_A);
ok(mutex_class_A != NULL, "mutex info A");
rwlock_class_A= find_rwlock_class(rwlock_key_A);
ok(rwlock_class_A != NULL, "rwlock info A");
cond_class_A= find_cond_class(cond_key_A);
ok(cond_class_A != NULL, "cond info A");
file_class_A= find_file_class(file_key_A);
ok(file_class_A != NULL, "file info A");
/* Pretend thread T-1 is running, and enabled */
/* ------------------------------------------ */
psi->set_thread(thread_1);
setup_thread(thread_1, true);
/* Enable all instruments, instantiate objects */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
ok(mutex_A1 != NULL, "instrumented");
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
ok(rwlock_A1 != NULL, "instrumented");
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(cond_key_A, NULL);
ok(cond_A1 != NULL, "instrumented");
file_class_A->m_enabled= true;
psi->create_file(file_key_A, "foo", (File) 12);
file_A1= (PSI_file*) lookup_file_by_name("foo");
ok(file_A1 != NULL, "instrumented");
PSI_mutex_locker *mutex_locker;
PSI_mutex_locker_state mutex_state;
PSI_rwlock_locker *rwlock_locker;
PSI_rwlock_locker_state rwlock_state;
PSI_cond_locker *cond_locker;
PSI_cond_locker_state cond_state;
PSI_file_locker *file_locker;
PSI_file_locker_state file_state;
/* Pretend thread T-1 is disabled */
/* ------------------------------ */
setup_thread(thread_1, false);
flag_events_waits_current= true;
mutex_class_A->m_enabled= true;
rwlock_class_A->m_enabled= true;
cond_class_A->m_enabled= true;
file_class_A->m_enabled= true;
mutex_locker= psi->get_thread_mutex_locker(&mutex_state, mutex_A1, PSI_MUTEX_LOCK);
ok(mutex_locker == NULL, "no locker");
rwlock_locker= psi->get_thread_rwlock_locker(&rwlock_state, rwlock_A1, PSI_RWLOCK_READLOCK);
ok(rwlock_locker == NULL, "no locker");
cond_locker= psi->get_thread_cond_locker(&cond_state, cond_A1, mutex_A1, PSI_COND_WAIT);
ok(cond_locker == NULL, "no locker");
file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "xxx", NULL);
ok(file_locker == NULL, "no locker");
file_locker= psi->get_thread_file_stream_locker(&file_state, file_A1, PSI_FILE_READ);
ok(file_locker == NULL, "no locker");
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
ok(file_locker == NULL, "no locker");
/* Pretend the consumer is disabled */
/* -------------------------------- */
setup_thread(thread_1, true);
flag_events_waits_current= false;
mutex_class_A->m_enabled= true;
rwlock_class_A->m_enabled= true;
cond_class_A->m_enabled= true;
file_class_A->m_enabled= true;
mutex_locker= psi->get_thread_mutex_locker(&mutex_state, mutex_A1, PSI_MUTEX_LOCK);
ok(mutex_locker == NULL, "no locker");
rwlock_locker= psi->get_thread_rwlock_locker(&rwlock_state, rwlock_A1, PSI_RWLOCK_READLOCK);
ok(rwlock_locker == NULL, "no locker");
cond_locker= psi->get_thread_cond_locker(&cond_state, cond_A1, mutex_A1, PSI_COND_WAIT);
ok(cond_locker == NULL, "no locker");
file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "xxx", NULL);
ok(file_locker == NULL, "no locker");
file_locker= psi->get_thread_file_stream_locker(&file_state, file_A1, PSI_FILE_READ);
ok(file_locker == NULL, "no locker");
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
ok(file_locker == NULL, "no locker");
/* Pretend the instrument is disabled */
/* ---------------------------------- */
setup_thread(thread_1, true);
flag_events_waits_current= true;
mutex_class_A->m_enabled= false;
rwlock_class_A->m_enabled= false;
cond_class_A->m_enabled= false;
file_class_A->m_enabled= false;
mutex_locker= psi->get_thread_mutex_locker(&mutex_state, mutex_A1, PSI_MUTEX_LOCK);
ok(mutex_locker == NULL, "no locker");
rwlock_locker= psi->get_thread_rwlock_locker(&rwlock_state, rwlock_A1, PSI_RWLOCK_READLOCK);
ok(rwlock_locker == NULL, "no locker");
cond_locker= psi->get_thread_cond_locker(&cond_state, cond_A1, mutex_A1, PSI_COND_WAIT);
ok(cond_locker == NULL, "no locker");
file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "xxx", NULL);
ok(file_locker == NULL, "no locker");
file_locker= psi->get_thread_file_stream_locker(&file_state, file_A1, PSI_FILE_READ);
ok(file_locker == NULL, "no locker");
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
ok(file_locker == NULL, "no locker");
/* Pretend everything is enabled */
/* ----------------------------- */
setup_thread(thread_1, true);
flag_events_waits_current= true;
mutex_class_A->m_enabled= true;
rwlock_class_A->m_enabled= true;
cond_class_A->m_enabled= true;
file_class_A->m_enabled= true;
mutex_locker= psi->get_thread_mutex_locker(&mutex_state, mutex_A1, PSI_MUTEX_LOCK);
ok(mutex_locker != NULL, "locker");
psi->start_mutex_wait(mutex_locker, __FILE__, __LINE__);
psi->end_mutex_wait(mutex_locker, 0);
rwlock_locker= psi->get_thread_rwlock_locker(&rwlock_state, rwlock_A1, PSI_RWLOCK_READLOCK);
ok(rwlock_locker != NULL, "locker");
psi->start_rwlock_rdwait(rwlock_locker, __FILE__, __LINE__);
psi->end_rwlock_rdwait(rwlock_locker, 0);
cond_locker= psi->get_thread_cond_locker(&cond_state, cond_A1, mutex_A1, PSI_COND_WAIT);
ok(cond_locker != NULL, "locker");
psi->start_cond_wait(cond_locker, __FILE__, __LINE__);
psi->end_cond_wait(cond_locker, 0);
file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "xxx", NULL);
ok(file_locker != NULL, "locker");
psi->start_file_open_wait(file_locker, __FILE__, __LINE__);
psi->end_file_open_wait(file_locker);
file_locker= psi->get_thread_file_stream_locker(&file_state, file_A1, PSI_FILE_READ);
ok(file_locker != NULL, "locker");
psi->start_file_wait(file_locker, 10, __FILE__, __LINE__);
psi->end_file_wait(file_locker, 10);
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
ok(file_locker != NULL, "locker");
psi->start_file_wait(file_locker, 10, __FILE__, __LINE__);
psi->end_file_wait(file_locker, 10);
/* Pretend the running thread is not instrumented */
/* ---------------------------------------------- */
psi->delete_current_thread();
flag_events_waits_current= true;
mutex_class_A->m_enabled= true;
rwlock_class_A->m_enabled= true;
cond_class_A->m_enabled= true;
file_class_A->m_enabled= true;
mutex_locker= psi->get_thread_mutex_locker(&mutex_state, mutex_A1, PSI_MUTEX_LOCK);
ok(mutex_locker == NULL, "no locker");
rwlock_locker= psi->get_thread_rwlock_locker(&rwlock_state, rwlock_A1, PSI_RWLOCK_READLOCK);
ok(rwlock_locker == NULL, "no locker");
cond_locker= psi->get_thread_cond_locker(&cond_state, cond_A1, mutex_A1, PSI_COND_WAIT);
ok(cond_locker == NULL, "no locker");
file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "xxx", NULL);
ok(file_locker == NULL, "no locker");
file_locker= psi->get_thread_file_stream_locker(&file_state, file_A1, PSI_FILE_READ);
ok(file_locker == NULL, "no locker");
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
ok(file_locker == NULL, "no locker");
shutdown_performance_schema();
}
void test_file_instrumentation_leak()
{
PSI *psi;
diag("test_file_instrumentation_leak");
psi= load_perfschema();
PSI_file_key file_key_A;
PSI_file_key file_key_B;
PSI_file_info all_file[]=
{
{ & file_key_A, "F-A", 0},
{ & file_key_B, "F-B", 0}
};
PSI_thread_key thread_key_1;
PSI_thread_info all_thread[]=
{
{ & thread_key_1, "T-1", 0}
};
psi->register_file("test", all_file, 2);
psi->register_thread("test", all_thread, 1);
PFS_file_class *file_class_A;
PFS_file_class *file_class_B;
PSI_file_locker_state file_state;
PSI_thread *thread_1;
/* Preparation */
thread_1= psi->new_thread(thread_key_1, NULL, 0);
ok(thread_1 != NULL, "T-1");
psi->set_thread_id(thread_1, 1);
file_class_A= find_file_class(file_key_A);
ok(file_class_A != NULL, "file info A");
file_class_B= find_file_class(file_key_B);
ok(file_class_B != NULL, "file info B");
psi->set_thread(thread_1);
/* Pretend everything is enabled */
/* ----------------------------- */
setup_thread(thread_1, true);
flag_events_waits_current= true;
file_class_A->m_enabled= true;
file_class_B->m_enabled= true;
PSI_file_locker *file_locker;
/* Simulate OPEN + READ of 100 bytes + CLOSE on descriptor 12 */
file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "AAA", NULL);
ok(file_locker != NULL, "locker");
psi->start_file_open_wait(file_locker, __FILE__, __LINE__);
psi->end_file_open_wait_and_bind_to_descriptor(file_locker, 12);
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
ok(file_locker != NULL, "locker");
psi->start_file_wait(file_locker, 100, __FILE__, __LINE__);
psi->end_file_wait(file_locker, 100);
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_CLOSE);
ok(file_locker != NULL, "locker");
psi->start_file_wait(file_locker, 0, __FILE__, __LINE__);
psi->end_file_wait(file_locker, 0);
/* Simulate uninstrumented-OPEN + WRITE on descriptor 24 */
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 24, PSI_FILE_WRITE);
ok(file_locker == NULL, "no locker, since the open was not instrumented");
/*
Simulate uninstrumented-OPEN + WRITE on descriptor 12 :
the instrumentation should not leak (don't charge the file io on unknown B to "AAA")
*/
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_WRITE);
ok(file_locker == NULL, "no locker, no leak");
shutdown_performance_schema();
}
void test_enabled()
{
#ifdef LATER
PSI *psi;
diag("test_enabled");
psi= load_perfschema();
PSI_mutex_key mutex_key_A;
PSI_mutex_key mutex_key_B;
PSI_mutex_info all_mutex[]=
{
{ & mutex_key_A, "M-A", 0},
{ & mutex_key_B, "M-B", 0}
};
PSI_rwlock_key rwlock_key_A;
PSI_rwlock_key rwlock_key_B;
PSI_rwlock_info all_rwlock[]=
{
{ & rwlock_key_A, "RW-A", 0},
{ & rwlock_key_B, "RW-B", 0}
};
PSI_cond_key cond_key_A;
PSI_cond_key cond_key_B;
PSI_cond_info all_cond[]=
{
{ & cond_key_A, "C-A", 0},
{ & cond_key_B, "C-B", 0}
};
shutdown_performance_schema();
#endif
}
void do_all_tests()
{
test_bootstrap();
test_bad_registration();
test_init_disabled();
test_locker_disabled();
test_file_instrumentation_leak();
}
int main(int, char **)
{
plan(153);
MY_INIT("pfs-t");
do_all_tests();
return 0;
}