1 | /* Copyright (C) MariaDB Corporation Ab |
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 as published by |
5 | the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, |
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | GNU General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software |
14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ |
15 | |
16 | /** |
17 | @file user_connect.cc |
18 | |
19 | @brief |
20 | Implements the user_connect class. |
21 | |
22 | @details |
23 | To support multi_threading, each query creates and use a PlugDB "user" |
24 | that is a connection with its personnal memory allocation. |
25 | |
26 | @note |
27 | Author Olivier Bertrand |
28 | */ |
29 | |
30 | /****************************************************************************/ |
31 | /* Author: Olivier Bertrand -- bertrandop@gmail.com -- 2004-2015 */ |
32 | /****************************************************************************/ |
33 | #ifdef USE_PRAGMA_IMPLEMENTATION |
34 | #pragma implementation // gcc: Class implementation |
35 | #endif |
36 | |
37 | #define DONT_DEFINE_VOID |
38 | #define MYSQL_SERVER |
39 | #include <my_global.h> |
40 | #include "sql_class.h" |
41 | #undef OFFSET |
42 | |
43 | #define NOPARSE |
44 | #include "osutil.h" |
45 | #include "global.h" |
46 | #include "plgdbsem.h" |
47 | #include "connect.h" |
48 | #include "user_connect.h" |
49 | #include "mycat.h" |
50 | |
51 | extern pthread_mutex_t usrmut; |
52 | |
53 | /****************************************************************************/ |
54 | /* Initialize the user_connect static member. */ |
55 | /****************************************************************************/ |
56 | PCONNECT user_connect::to_users= NULL; |
57 | |
58 | /****************************************************************************/ |
59 | /* Get the work_size SESSION variable value . */ |
60 | /****************************************************************************/ |
61 | uint GetWorkSize(void); |
62 | void SetWorkSize(uint); |
63 | |
64 | /* -------------------------- class user_connect -------------------------- */ |
65 | |
66 | /****************************************************************************/ |
67 | /* Constructor. */ |
68 | /****************************************************************************/ |
69 | user_connect::user_connect(THD *thd) |
70 | { |
71 | thdp= thd; |
72 | next= NULL; |
73 | previous= NULL; |
74 | g= NULL; |
75 | last_query_id= 0; |
76 | count= 0; |
77 | |
78 | // Statistics |
79 | nrd= fnd= nfd= 0; |
80 | tb1= 0; |
81 | } // end of user_connect constructor |
82 | |
83 | |
84 | /****************************************************************************/ |
85 | /* Destructor. */ |
86 | /****************************************************************************/ |
87 | user_connect::~user_connect() |
88 | { |
89 | // Terminate CONNECT and Plug-like environment, should return NULL |
90 | g= CntExit(g); |
91 | } // end of user_connect destructor |
92 | |
93 | |
94 | /****************************************************************************/ |
95 | /* Initialization. */ |
96 | /****************************************************************************/ |
97 | bool user_connect::user_init() |
98 | { |
99 | // Initialize Plug-like environment |
100 | uint worksize= GetWorkSize(); |
101 | PACTIVITY ap= NULL; |
102 | PDBUSER dup= NULL; |
103 | |
104 | // Areasize= 64M because of VEC tables. Should be parameterisable |
105 | //g= PlugInit(NULL, 67108864); |
106 | //g= PlugInit(NULL, 134217728); // 128M was because of old embedded tests |
107 | g= PlugInit(NULL, worksize); |
108 | |
109 | // Check whether the initialization is complete |
110 | if (!g || !g->Sarea || PlugSubSet(g, g->Sarea, g->Sarea_Size) |
111 | || !(dup= PlgMakeUser(g))) { |
112 | if (g) |
113 | printf("%s\n" , g->Message); |
114 | |
115 | int rc= PlugExit(g); |
116 | g= NULL; |
117 | |
118 | if (dup) |
119 | free(dup); |
120 | |
121 | return true; |
122 | } // endif g-> |
123 | |
124 | dup->Catalog= new MYCAT(NULL); |
125 | |
126 | ap= new ACTIVITY; |
127 | memset(ap, 0, sizeof(ACTIVITY)); |
128 | strcpy(ap->Ap_Name, "CONNECT" ); |
129 | g->Activityp= ap; |
130 | g->Activityp->Aptr= dup; |
131 | |
132 | pthread_mutex_lock(&usrmut); |
133 | next= to_users; |
134 | to_users= this; |
135 | |
136 | if (next) |
137 | next->previous= this; |
138 | |
139 | count = 1; |
140 | pthread_mutex_unlock(&usrmut); |
141 | |
142 | last_query_id= thdp->query_id; |
143 | return false; |
144 | } // end of user_init |
145 | |
146 | |
147 | void user_connect::SetHandler(ha_connect *hc) |
148 | { |
149 | PDBUSER dup= (PDBUSER)g->Activityp->Aptr; |
150 | MYCAT *mc= (MYCAT*)dup->Catalog; |
151 | mc->SetHandler(hc); |
152 | } |
153 | |
154 | /****************************************************************************/ |
155 | /* Check whether we begin a new query and if so cleanup the previous one. */ |
156 | /****************************************************************************/ |
157 | bool user_connect::CheckCleanup(bool force) |
158 | { |
159 | if (thdp->query_id > last_query_id || force) { |
160 | uint worksize= GetWorkSize(), size = g->Sarea_Size; |
161 | |
162 | PlugCleanup(g, true); |
163 | |
164 | if (size != worksize) { |
165 | FreeSarea(g); |
166 | |
167 | // Check whether the work area could be allocated |
168 | if (AllocSarea(g, worksize)) { |
169 | AllocSarea(g, size); |
170 | SetWorkSize(g->Sarea_Size); // Was too big |
171 | } // endif sarea |
172 | |
173 | } // endif worksize |
174 | |
175 | PlugSubSet(g, g->Sarea, g->Sarea_Size); |
176 | g->Xchk = NULL; |
177 | g->Createas = 0; |
178 | g->Alchecked = 0; |
179 | g->Mrr = 0; |
180 | last_query_id= thdp->query_id; |
181 | |
182 | if (trace(65) && !force) |
183 | printf("=====> Begin new query %llu\n" , last_query_id); |
184 | |
185 | return true; |
186 | } // endif query_id |
187 | |
188 | return false; |
189 | } // end of CheckCleanup |
190 | |
191 | |