| 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 | |