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 /**
24 @file
25 Server session service implementation. For more information please check
26 the function comments.
27 */
28 #include "srv_session.h"
29 /*
30 service_srv_session.h should not be first to be included as it will include
31 - include/mysql/service_srv_session.h
32 - include/mysql/plugin.h
33 - include/mysql/services.h
34 - include/mysql/service_command.h
35 which in turn will need MYSQL_SESSION but won't see it, as it will be
36 declared after the includes.
37 */
38 #include "mysql/service_srv_session.h"
39 #include "sql_class.h"
40 #include "conn_handler/connection_handler_manager.h"
41
42 extern "C"
43 {
44
45 /**
46 Initializes physical thread to use with session service.
47
48 @return
49 0 success
50 1 failure
51 */
srv_session_init_thread(const void * plugin)52 int srv_session_init_thread(const void *plugin)
53 {
54 return Srv_session::init_thread(plugin);
55 }
56
57
58 /**
59 Deinitializes physical thread to use with session service
60 */
srv_session_deinit_thread()61 void srv_session_deinit_thread()
62 {
63 Srv_session::deinit_thread();
64 }
65
66
67 /**
68 Opens server session
69
70 @param error_cb Default completion callback
71 @param plugin_ctx Plugin's context, opaque pointer that would
72 be provided to callbacks. Might be NULL.
73 @return
74 handler of session on success
75 NULL on failure
76 */
srv_session_open(srv_session_error_cb error_cb,void * plugin_ctx)77 Srv_session* srv_session_open(srv_session_error_cb error_cb, void *plugin_ctx)
78 {
79 DBUG_ENTER("srv_session_open");
80
81 if (!srv_session_server_is_available())
82 {
83 if (error_cb)
84 error_cb(plugin_ctx, ER_SERVER_ISNT_AVAILABLE,
85 ER_DEFAULT(ER_SERVER_ISNT_AVAILABLE));
86 DBUG_RETURN(NULL);
87 }
88
89 bool simulate_reach_max_connections= false;
90 DBUG_EXECUTE_IF("simulate_reach_max_connections",
91 simulate_reach_max_connections= true;);
92
93 Connection_handler_manager *conn_manager=
94 Connection_handler_manager::get_instance();
95
96 if (simulate_reach_max_connections ||
97 !conn_manager->check_and_incr_conn_count(false))
98 {
99 if (error_cb)
100 error_cb(plugin_ctx, ER_CON_COUNT_ERROR, ER_DEFAULT(ER_CON_COUNT_ERROR));
101 DBUG_RETURN(NULL);
102 }
103
104 Srv_session* session= new (std::nothrow) class Srv_session(error_cb, plugin_ctx);
105
106 if (!session)
107 {
108 DBUG_PRINT("error", ("Can't allocate a Srv_session object"));
109 connection_errors_internal++;
110 if (error_cb)
111 error_cb(plugin_ctx, ER_OUT_OF_RESOURCES, ER_DEFAULT(ER_OUT_OF_RESOURCES));
112 }
113 else
114 {
115 THD *current= current_thd;
116 THD *stack_thd= session->get_thd();
117
118 session->get_thd()->thread_stack= reinterpret_cast<char *>(&stack_thd);
119 session->get_thd()->store_globals();
120
121 bool result= session->open();
122
123 session->get_thd()->restore_globals();
124
125 if (result)
126 {
127 delete session;
128 session= NULL;
129 }
130
131 if (current)
132 current->store_globals();
133 }
134 DBUG_RETURN(session);
135 }
136
137
138 /**
139 Detaches a session from current physical thread.
140
141 @param session Session handle to detach
142
143 @returns
144 0 success
145 1 failure
146 */
srv_session_detach(Srv_session * session)147 int srv_session_detach(Srv_session* session)
148 {
149 DBUG_ENTER("srv_session_detach");
150
151 if (!session || !Srv_session::is_valid(session))
152 {
153 DBUG_PRINT("error", ("Session is not valid"));
154 DBUG_RETURN(true);
155 }
156
157 DBUG_RETURN(session->detach());
158 }
159
160
161 /**
162 Closes a session.
163
164 @param session Session handle to close
165
166 @returns
167 0 Session successfully closed
168 1 Session wasn't found or key doesn't match
169 */
srv_session_close(Srv_session * session)170 int srv_session_close(Srv_session* session)
171 {
172 DBUG_ENTER("srv_session_close");
173
174 if (!session || !Srv_session::is_valid(session))
175 {
176 DBUG_PRINT("error", ("Session is not valid"));
177 DBUG_RETURN(1);
178 }
179
180 session->close();
181 delete session;
182
183 /*
184 Here we don't need to reattach the previous session, as the next
185 function (run_command() for example) will attach to whatever is needed.
186 */
187 DBUG_RETURN(0);
188 }
189
190 /**
191 Returns if the server is available (not booting or shutting down)
192
193 @return
194 0 not available
195 1 available
196 */
srv_session_server_is_available()197 int srv_session_server_is_available()
198 {
199 return get_server_state() == SERVER_OPERATING;
200 }
201
202 } /* extern "C" */
203