1 | /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. |
2 | |
3 | This program is free software; you can redistribute it and/or modify |
4 | it under the terms of the GNU General Public License as published by |
5 | the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, |
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | GNU General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software |
14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
15 | |
16 | /* |
17 | * sql_manager.cc |
18 | * This thread manages various maintenance tasks. |
19 | * |
20 | * o Flushing the tables every flush_time seconds. |
21 | * o Berkeley DB: removing unneeded log files. |
22 | */ |
23 | |
24 | #include "mariadb.h" |
25 | #include "sql_priv.h" |
26 | #include "sql_manager.h" |
27 | #include "sql_base.h" // flush_tables |
28 | |
29 | static bool volatile manager_thread_in_use; |
30 | static bool abort_manager; |
31 | |
32 | pthread_t manager_thread; |
33 | mysql_mutex_t LOCK_manager; |
34 | mysql_cond_t COND_manager; |
35 | |
36 | struct handler_cb { |
37 | struct handler_cb *next; |
38 | void (*action)(void); |
39 | }; |
40 | |
41 | static struct handler_cb * volatile cb_list; |
42 | |
43 | bool mysql_manager_submit(void (*action)()) |
44 | { |
45 | bool result= FALSE; |
46 | DBUG_ASSERT(manager_thread_in_use); |
47 | struct handler_cb * volatile *cb; |
48 | mysql_mutex_lock(&LOCK_manager); |
49 | cb= &cb_list; |
50 | while (*cb && (*cb)->action != action) |
51 | cb= &(*cb)->next; |
52 | if (!*cb) |
53 | { |
54 | *cb= (struct handler_cb *)my_malloc(sizeof(struct handler_cb), MYF(MY_WME)); |
55 | if (!*cb) |
56 | result= TRUE; |
57 | else |
58 | { |
59 | (*cb)->next= NULL; |
60 | (*cb)->action= action; |
61 | } |
62 | } |
63 | mysql_mutex_unlock(&LOCK_manager); |
64 | return result; |
65 | } |
66 | |
67 | pthread_handler_t handle_manager(void *arg __attribute__((unused))) |
68 | { |
69 | int error = 0; |
70 | struct timespec abstime; |
71 | bool reset_flush_time = TRUE; |
72 | struct handler_cb *cb= NULL; |
73 | my_thread_init(); |
74 | DBUG_ENTER("handle_manager" ); |
75 | |
76 | pthread_detach_this_thread(); |
77 | manager_thread = pthread_self(); |
78 | mysql_cond_init(key_COND_manager, &COND_manager,NULL); |
79 | mysql_mutex_init(key_LOCK_manager, &LOCK_manager, NULL); |
80 | manager_thread_in_use = 1; |
81 | for (;;) |
82 | { |
83 | mysql_mutex_lock(&LOCK_manager); |
84 | /* XXX: This will need to be made more general to handle different |
85 | * polling needs. */ |
86 | if (flush_time) |
87 | { |
88 | if (reset_flush_time) |
89 | { |
90 | set_timespec(abstime, flush_time); |
91 | reset_flush_time = FALSE; |
92 | } |
93 | while ((!error || error == EINTR) && !abort_manager) |
94 | error= mysql_cond_timedwait(&COND_manager, &LOCK_manager, &abstime); |
95 | } |
96 | else |
97 | { |
98 | while ((!error || error == EINTR) && !abort_manager) |
99 | error= mysql_cond_wait(&COND_manager, &LOCK_manager); |
100 | } |
101 | if (cb == NULL) |
102 | { |
103 | cb= cb_list; |
104 | cb_list= NULL; |
105 | } |
106 | mysql_mutex_unlock(&LOCK_manager); |
107 | |
108 | if (abort_manager) |
109 | break; |
110 | |
111 | if (error == ETIMEDOUT || error == ETIME) |
112 | { |
113 | tc_purge(); |
114 | error = 0; |
115 | reset_flush_time = TRUE; |
116 | } |
117 | |
118 | while (cb) |
119 | { |
120 | struct handler_cb *next= cb->next; |
121 | cb->action(); |
122 | my_free(cb); |
123 | cb= next; |
124 | } |
125 | } |
126 | manager_thread_in_use = 0; |
127 | mysql_mutex_destroy(&LOCK_manager); |
128 | mysql_cond_destroy(&COND_manager); |
129 | DBUG_LEAVE; // Can't use DBUG_RETURN after my_thread_end |
130 | my_thread_end(); |
131 | return (NULL); |
132 | } |
133 | |
134 | |
135 | /* Start handle manager thread */ |
136 | void start_handle_manager() |
137 | { |
138 | DBUG_ENTER("start_handle_manager" ); |
139 | abort_manager = false; |
140 | if (flush_time && flush_time != ~(ulong) 0L) |
141 | { |
142 | pthread_t hThread; |
143 | int error; |
144 | if ((error= mysql_thread_create(key_thread_handle_manager, |
145 | &hThread, &connection_attrib, |
146 | handle_manager, 0))) |
147 | sql_print_warning("Can't create handle_manager thread (errno= %d)" , |
148 | error); |
149 | } |
150 | DBUG_VOID_RETURN; |
151 | } |
152 | |
153 | |
154 | /* Initiate shutdown of handle manager thread */ |
155 | void stop_handle_manager() |
156 | { |
157 | DBUG_ENTER("stop_handle_manager" ); |
158 | abort_manager = true; |
159 | if (manager_thread_in_use) |
160 | { |
161 | mysql_mutex_lock(&LOCK_manager); |
162 | DBUG_PRINT("quit" , ("initiate shutdown of handle manager thread: %lu" , |
163 | (ulong)manager_thread)); |
164 | mysql_cond_signal(&COND_manager); |
165 | mysql_mutex_unlock(&LOCK_manager); |
166 | } |
167 | DBUG_VOID_RETURN; |
168 | } |
169 | |
170 | |