1 | /* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights |
2 | reserved. |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by |
6 | the Free Software Foundation; version 2 of the License. |
7 | |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | GNU General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU General Public License |
14 | along with this program; if not, write to the Free Software |
15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
16 | |
17 | #include <my_global.h> |
18 | #include <sql_priv.h> |
19 | #include <stdlib.h> |
20 | #include <ctype.h> |
21 | #include <mysql_version.h> |
22 | #include <mysql/plugin.h> |
23 | #include <my_dir.h> |
24 | #include "my_pthread.h" // pthread_handler_t |
25 | #include "my_sys.h" // my_write, my_malloc |
26 | #include "m_string.h" // strlen |
27 | #include "sql_plugin.h" // st_plugin_int |
28 | |
29 | /* |
30 | Disable __attribute__() on non-gcc compilers. |
31 | */ |
32 | #if !defined(__attribute__) && !defined(__GNUC__) |
33 | #define __attribute__(A) |
34 | #endif |
35 | |
36 | |
37 | #define HEART_STRING_BUFFER 100 |
38 | |
39 | struct mysql_heartbeat_context |
40 | { |
41 | pthread_t heartbeat_thread; |
42 | File heartbeat_file; |
43 | }; |
44 | |
45 | pthread_handler_t mysql_heartbeat(void *p) |
46 | { |
47 | DBUG_ENTER("mysql_heartbeat" ); |
48 | struct mysql_heartbeat_context *con= (struct mysql_heartbeat_context *)p; |
49 | char buffer[HEART_STRING_BUFFER]; |
50 | time_t result; |
51 | struct tm tm_tmp; |
52 | |
53 | while(1) |
54 | { |
55 | sleep(5); |
56 | |
57 | result= time(NULL); |
58 | localtime_r(&result, &tm_tmp); |
59 | my_snprintf(buffer, sizeof(buffer), |
60 | "Heartbeat at %02d%02d%02d %2d:%02d:%02d\n" , |
61 | tm_tmp.tm_year % 100, |
62 | tm_tmp.tm_mon+1, |
63 | tm_tmp.tm_mday, |
64 | tm_tmp.tm_hour, |
65 | tm_tmp.tm_min, |
66 | tm_tmp.tm_sec); |
67 | my_write(con->heartbeat_file, (uchar*) buffer, strlen(buffer), MYF(0)); |
68 | } |
69 | |
70 | DBUG_RETURN(0); |
71 | } |
72 | |
73 | /* |
74 | Initialize the daemon example at server start or plugin installation. |
75 | |
76 | SYNOPSIS |
77 | daemon_example_plugin_init() |
78 | |
79 | DESCRIPTION |
80 | Starts up heartbeatbeat thread |
81 | |
82 | RETURN VALUE |
83 | 0 success |
84 | 1 failure (cannot happen) |
85 | */ |
86 | |
87 | static int daemon_example_plugin_init(void *p __attribute__ ((unused))) |
88 | { |
89 | |
90 | DBUG_ENTER("daemon_example_plugin_init" ); |
91 | struct mysql_heartbeat_context *con; |
92 | pthread_attr_t attr; /* Thread attributes */ |
93 | char heartbeat_filename[FN_REFLEN]; |
94 | char buffer[HEART_STRING_BUFFER]; |
95 | time_t result= time(NULL); |
96 | struct tm tm_tmp; |
97 | |
98 | struct st_plugin_int *plugin= (struct st_plugin_int *)p; |
99 | |
100 | con= (struct mysql_heartbeat_context *) |
101 | my_malloc(sizeof(struct mysql_heartbeat_context), MYF(0)); |
102 | |
103 | fn_format(heartbeat_filename, "mysql-heartbeat" , "" , ".log" , |
104 | MY_REPLACE_EXT | MY_UNPACK_FILENAME); |
105 | unlink(heartbeat_filename); |
106 | con->heartbeat_file= my_open(heartbeat_filename, O_CREAT|O_RDWR, MYF(0)); |
107 | |
108 | /* |
109 | No threads exist at this point in time, so this is thread safe. |
110 | */ |
111 | localtime_r(&result, &tm_tmp); |
112 | my_snprintf(buffer, sizeof(buffer), |
113 | "Starting up at %02d%02d%02d %2d:%02d:%02d\n" , |
114 | tm_tmp.tm_year % 100, |
115 | tm_tmp.tm_mon+1, |
116 | tm_tmp.tm_mday, |
117 | tm_tmp.tm_hour, |
118 | tm_tmp.tm_min, |
119 | tm_tmp.tm_sec); |
120 | my_write(con->heartbeat_file, (uchar*) buffer, strlen(buffer), MYF(0)); |
121 | |
122 | pthread_attr_init(&attr); |
123 | pthread_attr_setdetachstate(&attr, |
124 | PTHREAD_CREATE_JOINABLE); |
125 | |
126 | |
127 | /* now create the thread */ |
128 | if (pthread_create(&con->heartbeat_thread, &attr, mysql_heartbeat, |
129 | (void *)con) != 0) |
130 | { |
131 | fprintf(stderr,"Could not create heartbeat thread!\n" ); |
132 | DBUG_RETURN(1); |
133 | } |
134 | plugin->data= (void *)con; |
135 | |
136 | DBUG_RETURN(0); |
137 | } |
138 | |
139 | |
140 | /* |
141 | Terminate the daemon example at server shutdown or plugin deinstallation. |
142 | |
143 | SYNOPSIS |
144 | daemon_example_plugin_deinit() |
145 | Does nothing. |
146 | |
147 | RETURN VALUE |
148 | 0 success |
149 | 1 failure (cannot happen) |
150 | |
151 | */ |
152 | |
153 | static int daemon_example_plugin_deinit(void *p __attribute__ ((unused))) |
154 | { |
155 | DBUG_ENTER("daemon_example_plugin_deinit" ); |
156 | char buffer[HEART_STRING_BUFFER]; |
157 | struct st_plugin_int *plugin= (struct st_plugin_int *)p; |
158 | struct mysql_heartbeat_context *con= |
159 | (struct mysql_heartbeat_context *)plugin->data; |
160 | time_t result= time(NULL); |
161 | struct tm tm_tmp; |
162 | |
163 | pthread_cancel(con->heartbeat_thread); |
164 | pthread_join(con->heartbeat_thread, NULL); |
165 | |
166 | localtime_r(&result, &tm_tmp); |
167 | my_snprintf(buffer, sizeof(buffer), |
168 | "Shutting down at %02d%02d%02d %2d:%02d:%02d\n" , |
169 | tm_tmp.tm_year % 100, |
170 | tm_tmp.tm_mon+1, |
171 | tm_tmp.tm_mday, |
172 | tm_tmp.tm_hour, |
173 | tm_tmp.tm_min, |
174 | tm_tmp.tm_sec); |
175 | my_write(con->heartbeat_file, (uchar*) buffer, strlen(buffer), MYF(0)); |
176 | |
177 | /* |
178 | Need to wait for the hearbeat thread to terminate before closing |
179 | the file it writes to and freeing the memory it uses. |
180 | */ |
181 | pthread_join(con->heartbeat_thread, NULL); |
182 | |
183 | my_close(con->heartbeat_file, MYF(0)); |
184 | |
185 | my_free(con); |
186 | |
187 | DBUG_RETURN(0); |
188 | } |
189 | |
190 | |
191 | struct st_mysql_daemon daemon_example_plugin= |
192 | { MYSQL_DAEMON_INTERFACE_VERSION }; |
193 | |
194 | /* |
195 | Plugin library descriptor |
196 | */ |
197 | |
198 | maria_declare_plugin(daemon_example) |
199 | { |
200 | MYSQL_DAEMON_PLUGIN, |
201 | &daemon_example_plugin, |
202 | "daemon_example" , |
203 | "Brian Aker" , |
204 | "Daemon example, creates a heartbeat beat file in mysql-heartbeat.log" , |
205 | PLUGIN_LICENSE_GPL, |
206 | daemon_example_plugin_init, /* Plugin Init */ |
207 | daemon_example_plugin_deinit, /* Plugin Deinit */ |
208 | 0x0100 /* 1.0 */, |
209 | NULL, /* status variables */ |
210 | NULL, /* system variables */ |
211 | "1.0" , /* string version */ |
212 | MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */ |
213 | } |
214 | maria_declare_plugin_end; |
215 | |