Commit c62c0c55 authored by Sergey Petrunya's avatar Sergey Petrunya

MWL#182: Explain running statements: address review feedback

- Add Monty Program Ab copyright in new files
- Change Apc_target::make_apc_call() to accept a C++-style
  functor (instead of C-style function + parameter)
parent 66c62de1
/* /*
TODO: MP AB Copyright Copyright (c) 2009, 2011, Monty Program Ab
*/
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 */
#ifdef MY_APC_STANDALONE #ifdef MY_APC_STANDALONE
...@@ -139,8 +151,8 @@ void Apc_target::dequeue_request(Call_request *qe) ...@@ -139,8 +151,8 @@ void Apc_target::dequeue_request(Call_request *qe)
to use thd->enter_cond() calls to be killable) to use thd->enter_cond() calls to be killable)
*/ */
bool Apc_target::make_apc_call(apc_func_t func, void *func_arg, bool Apc_target::make_apc_call(Apc_call *call, int timeout_sec,
int timeout_sec, bool *timed_out) bool *timed_out)
{ {
bool res= TRUE; bool res= TRUE;
*timed_out= FALSE; *timed_out= FALSE;
...@@ -149,8 +161,7 @@ bool Apc_target::make_apc_call(apc_func_t func, void *func_arg, ...@@ -149,8 +161,7 @@ bool Apc_target::make_apc_call(apc_func_t func, void *func_arg,
{ {
/* Create and post the request */ /* Create and post the request */
Call_request apc_request; Call_request apc_request;
apc_request.func= func; apc_request.call= call;
apc_request.func_arg= func_arg;
apc_request.processed= FALSE; apc_request.processed= FALSE;
mysql_cond_init(0 /* do not track in PS */, &apc_request.COND_request, NULL); mysql_cond_init(0 /* do not track in PS */, &apc_request.COND_request, NULL);
enqueue_request(&apc_request); enqueue_request(&apc_request);
...@@ -229,7 +240,7 @@ void Apc_target::process_apc_requests() ...@@ -229,7 +240,7 @@ void Apc_target::process_apc_requests()
dequeue_request(request); dequeue_request(request);
request->processed= TRUE; request->processed= TRUE;
request->func(request->func_arg); request->call->call_in_target_thread();
request->what="func called by process_apc_requests"; request->what="func called by process_apc_requests";
#ifndef DBUG_OFF #ifndef DBUG_OFF
......
/* /*
TODO: MP AB Copyright Copyright (c) 2009, 2011, Monty Program Ab
*/
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 */
/* /*
Interface Interface
...@@ -38,8 +50,12 @@ class Apc_target ...@@ -38,8 +50,12 @@ class Apc_target
void process_apc_requests(); void process_apc_requests();
typedef void (*apc_func_t)(void *arg); class Apc_call
{
public:
virtual void call_in_target_thread()= 0;
virtual ~Apc_call() {}
};
/* /*
Make an APC call: schedule it for execution and wait until the target Make an APC call: schedule it for execution and wait until the target
thread has executed it. This function must not be called from a thread thread has executed it. This function must not be called from a thread
...@@ -49,8 +65,7 @@ class Apc_target ...@@ -49,8 +65,7 @@ class Apc_target
@retval TRUE - Call wasnt made (either the target is in disabled state or @retval TRUE - Call wasnt made (either the target is in disabled state or
timeout occured) timeout occured)
*/ */
bool make_apc_call(apc_func_t func, void *func_arg, bool make_apc_call(Apc_call *call, int timeout_sec, bool *timed_out);
int timeout_sec, bool *timed_out);
#ifndef DBUG_OFF #ifndef DBUG_OFF
int n_calls_processed; /* Number of calls served by this target */ int n_calls_processed; /* Number of calls served by this target */
...@@ -78,8 +93,7 @@ class Apc_target ...@@ -78,8 +93,7 @@ class Apc_target
class Call_request class Call_request
{ {
public: public:
apc_func_t func; /* Function to call */ Apc_call *call; /* Functor to be called */
void *func_arg; /* Argument to pass it */
/* The caller will actually wait for "processed==TRUE" */ /* The caller will actually wait for "processed==TRUE" */
bool processed; bool processed;
......
...@@ -3330,33 +3330,32 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup) ...@@ -3330,33 +3330,32 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
we're producing EXPLAIN for. we're producing EXPLAIN for.
*/ */
void Show_explain_request::get_explain_data(void *arg) void Show_explain_request::call_in_target_thread()
{ {
Show_explain_request *req= (Show_explain_request*)arg;
Query_arena backup_arena; Query_arena backup_arena;
THD *target_thd= req->target_thd;
bool printed_anything= FALSE; bool printed_anything= FALSE;
/* /*
Change the arena because JOIN::print_explain and co. are going to allocate Change the arena because JOIN::print_explain and co. are going to allocate
items. Let them allocate them on our arena. items. Let them allocate them on our arena.
*/ */
target_thd->set_n_backup_active_arena((Query_arena*)req->request_thd, target_thd->set_n_backup_active_arena((Query_arena*)request_thd,
&backup_arena); &backup_arena);
req->query_str.copy(target_thd->query(), query_str.copy(target_thd->query(),
target_thd->query_length(), target_thd->query_length(),
&my_charset_bin); &my_charset_bin);
if (target_thd->lex->unit.print_explain(req->explain_buf, 0 /* explain flags*/, if (target_thd->lex->unit.print_explain(explain_buf, 0 /* explain flags*/,
&printed_anything)) &printed_anything))
req->failed_to_produce= TRUE; {
failed_to_produce= TRUE;
}
if (!printed_anything) if (!printed_anything)
req->failed_to_produce= TRUE; failed_to_produce= TRUE;
target_thd->restore_active_arena((Query_arena*)req->request_thd, target_thd->restore_active_arena((Query_arena*)request_thd, &backup_arena);
&backup_arena);
} }
......
...@@ -1528,11 +1528,11 @@ class select_result_explain_buffer; ...@@ -1528,11 +1528,11 @@ class select_result_explain_buffer;
The thread that runs SHOW EXPLAIN statement creates a Show_explain_request The thread that runs SHOW EXPLAIN statement creates a Show_explain_request
object R, and then schedules APC call of object R, and then schedules APC call of
Show_explain_request::get_explain_data((void*)&R). Show_explain_request::call((void*)&R).
*/ */
class Show_explain_request class Show_explain_request : public Apc_target::Apc_call
{ {
public: public:
THD *target_thd; /* thd that we're running SHOW EXPLAIN for */ THD *target_thd; /* thd that we're running SHOW EXPLAIN for */
...@@ -1546,8 +1546,9 @@ class Show_explain_request ...@@ -1546,8 +1546,9 @@ class Show_explain_request
/* Query that we've got SHOW EXPLAIN for */ /* Query that we've got SHOW EXPLAIN for */
String query_str; String query_str;
static void get_explain_data(void *arg); /* Overloaded virtual function */
void call_in_target_thread();
}; };
class THD; class THD;
......
...@@ -2065,9 +2065,7 @@ void mysqld_show_explain(THD *thd, ulong thread_id) ...@@ -2065,9 +2065,7 @@ void mysqld_show_explain(THD *thd, ulong thread_id)
explain_req.failed_to_produce= FALSE; explain_req.failed_to_produce= FALSE;
/* Ok, we have a lock on target->LOCK_thd_data, can call: */ /* Ok, we have a lock on target->LOCK_thd_data, can call: */
bres= tmp->apc_target.make_apc_call(Show_explain_request::get_explain_data, bres= tmp->apc_target.make_apc_call(&explain_req, timeout_sec, &timed_out);
(void*)&explain_req,
timeout_sec, &timed_out);
if (bres || explain_req.failed_to_produce) if (bres || explain_req.failed_to_produce)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment