1 /* Copyright (c) 2015, 2021, Oracle and/or its affiliates.
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, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include <my_global.h>
24 #include <mysql_version.h>
25 #include <mysql/plugin.h>
26 #include "my_sys.h" // my_write, my_malloc
27 #include "m_string.h" // strlen
28 #include "sql_plugin.h" // st_plugin_int
29
30 #define STRING_BUFFER 256
31
32 File outfile;
33
34 struct test_services_context
35 {
36 my_thread_handle test_services_thread;
37 };
38
39 /* Shows status of test (Busy/READY) */
40 enum t_test_status { BUSY= 0, READY= 1 };
41 static t_test_status test_status;
42
43 /* declaration of status variable for plugin */
44 static struct st_mysql_show_var test_services_status[]=
45 {
46 { "test_services_status",
47 (char *) &test_status,
48 SHOW_INT, SHOW_SCOPE_GLOBAL },
49 {0, 0, SHOW_UNDEF, SHOW_SCOPE_GLOBAL}
50 };
51
52 /* SQL variables to control test execution */
53 /* SQL variables to switch on/off test of services, default=on */
54 /* Only be effective at start od mysqld by setting it as option --loose-... */
55 static int with_snprintf_val= 0;
56 static MYSQL_SYSVAR_INT (with_snprintf, with_snprintf_val , PLUGIN_VAR_RQCMDARG,
57 "Switch on/off test of snprintf service", NULL, NULL, 1, 0, 1, 0);
58
59 static int with_log_message_val= 0;
60 static MYSQL_SYSVAR_INT (with_log_message, with_log_message_val, PLUGIN_VAR_RQCMDARG,
61 "Switch on/off test of log message service", NULL, NULL, 1, 0, 1, 0);
62
63 static struct st_mysql_sys_var *test_services_sysvars[]= {
64 MYSQL_SYSVAR(with_snprintf),
65 MYSQL_SYSVAR(with_log_message),
66 NULL
67 };
68
69 /* The test cases for snprintf service. */
test_snprintf()70 int test_snprintf()
71 {
72 DBUG_ENTER("mysql_outfile");
73 char filename[FN_REFLEN];
74 char buffer[STRING_BUFFER];
75
76
77 fn_format(filename, "test_services", "", ".log",
78 MY_REPLACE_EXT | MY_UNPACK_FILENAME);
79 unlink(filename);
80 outfile= my_open(filename, O_CREAT|O_RDWR, MYF(0));
81
82 my_snprintf(buffer, sizeof(buffer),
83 "Starting test of my_snprintf in test_services_threaded.\n");
84 my_write(outfile, (uchar*) buffer, strlen(buffer), MYF(0));
85
86 my_snprintf(buffer, sizeof(buffer),
87 "This is a text output of test_services_threaded formatted with my_snprintf.\n");
88 my_write(outfile, (uchar*) buffer, strlen(buffer), MYF(0));
89
90 my_snprintf(buffer, sizeof(buffer),
91 "Shutting down test of my_snprintf in test_services_threaded.\n");
92 my_write(outfile, (uchar*) buffer, strlen(buffer), MYF(0));
93
94 my_close(outfile, MYF(0));
95
96 DBUG_RETURN(0);
97 }
98
99 /* The test cases for the log_message service. */
test_my_plugin_log_message(void * p)100 int test_my_plugin_log_message(void *p)
101 {
102 DBUG_ENTER("my_plugin_log_message");
103 /* Writes to mysqld.1.err: Plugin test_services reports an info text */
104 int ret = my_plugin_log_message(&p, MY_INFORMATION_LEVEL, "This is the test plugin for services");
105
106 /* Writes to mysqld.1.err: Plugin test_services reports a warning. */
107 ret = my_plugin_log_message(&p, MY_WARNING_LEVEL, "This is a warning from test plugin for services");
108
109 /* Writes to mysqld.1.err: Plugin test_services reports an error. */
110 ret = my_plugin_log_message(&p, MY_ERROR_LEVEL, "This is an error from test plugin for services");
111
112 DBUG_RETURN(ret);
113 }
114
115 /* This fucntion is needed to be called in a thread. */
test_services(void * p)116 void *test_services(void *p) {
117 DBUG_ENTER("test_services");
118
119 int ret= 0;
120
121 test_status= BUSY;
122 /* Test of service: snprintf */
123 /* Log the value of the switch in mysqld.err. */
124 ret = my_plugin_log_message(&p, MY_INFORMATION_LEVEL, "Test_services_threaded with_snprintf_val: %d",
125 with_snprintf_val);
126 if (with_snprintf_val==1){
127 ret= test_snprintf();
128 }
129 else {
130 ret = my_plugin_log_message(&p, MY_INFORMATION_LEVEL, "Test of snprintf switched off");
131 }
132
133 /* Test of service: my_plugin_log_message */
134 /* Log the value of the switch in mysqld.err. */
135 ret = my_plugin_log_message(&p, MY_INFORMATION_LEVEL, "Test_services_threaded with_log_message_val: %d",
136 with_log_message_val);
137 if (with_log_message_val==1){
138 ret= test_my_plugin_log_message(p);
139 }
140 else {
141 ret = my_plugin_log_message(&p, MY_INFORMATION_LEVEL, "Test of log_message switched off");
142 }
143
144 test_status= READY;
145
146 if (ret != 0) {
147 my_plugin_log_message(&p, MY_ERROR_LEVEL, "Test services return code: %d", ret);
148 }
149
150 DBUG_RETURN(0);
151 }
152
153 /* Creates the plugin context "con", which holds a pointer to the thread. */
test_services_plugin_init(void * p)154 static int test_services_plugin_init(void *p)
155 {
156 DBUG_ENTER("test_services_plugin_init");
157
158 int ret=0;
159
160 struct test_services_context *con;
161 my_thread_attr_t attr; /* Thread attributes */
162 struct st_plugin_int *plugin= (struct st_plugin_int *)p;
163 con= (struct test_services_context *)
164 my_malloc(PSI_INSTRUMENT_ME,
165 sizeof(struct test_services_context), MYF(0));
166 my_thread_attr_init(&attr);
167 (void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
168
169 /* now create the thread and call test_services within the thread. */
170 if (my_thread_create(&con->test_services_thread, &attr, test_services, p) != 0)
171 {
172 my_plugin_log_message(&p, MY_ERROR_LEVEL, "Could not create test services thread!");
173 exit(0);
174 }
175 plugin->data= (void *)con;
176
177 DBUG_RETURN(ret);
178 }
179
180 /* Clean up thread and frees plugin context "con". */
test_services_plugin_deinit(void * p)181 static int test_services_plugin_deinit(void *p)
182 {
183 DBUG_ENTER("test_services_plugin_deinit");
184 void *dummy_retval;
185 struct st_plugin_int *plugin= (struct st_plugin_int *)p;
186 struct test_services_context *con= (struct test_services_context *)plugin->data;
187 my_thread_cancel(&con->test_services_thread);
188 my_thread_join(&con->test_services_thread, &dummy_retval);
189 my_free(con);
190 DBUG_RETURN(0);
191 }
192
193 /* Mandatory structure describing the properties of the plugin. */
194 struct st_mysql_daemon test_services_plugin=
195 { MYSQL_DAEMON_INTERFACE_VERSION };
196
mysql_declare_plugin(test_daemon)197 mysql_declare_plugin(test_daemon)
198 {
199 MYSQL_DAEMON_PLUGIN,
200 &test_services_plugin,
201 "test_services_threaded",
202 "Horst Hunger",
203 "Test services with thread",
204 PLUGIN_LICENSE_GPL,
205 test_services_plugin_init, /* Plugin Init */
206 test_services_plugin_deinit, /* Plugin Deinit */
207 0x0100 /* 1.0 */,
208 test_services_status, /* status variables */
209 test_services_sysvars, /* system variables */
210 NULL, /* config options */
211 0, /* flags */
212 }
213 mysql_declare_plugin_end;
214