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