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 02110-1335 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-2020 */
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 size_t GetWorkSize(void);
62 void SetWorkSize(size_t);
63
64 /* -------------------------- class user_connect -------------------------- */
65
66 /****************************************************************************/
67 /* Constructor. */
68 /****************************************************************************/
user_connect(THD * thd)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 /****************************************************************************/
~user_connect()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 /****************************************************************************/
user_init()97 bool user_connect::user_init()
98 {
99 // Initialize Plug-like environment
100 size_t 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, (size_t)worksize);
108
109 // Check whether the initialization is complete
110 if (!g || !g->Sarea || PlugSubSet(g->Sarea, g->Sarea_Size)
111 || !(dup= PlgMakeUser(g))) {
112 if (g)
113 printf("%s\n", g->Message);
114
115 g= PlugExit(g);
116
117 if (dup)
118 free(dup);
119
120 return true;
121 } // endif g->
122
123 dup->Catalog= new MYCAT(NULL);
124
125 ap= new ACTIVITY;
126 memset(ap, 0, sizeof(ACTIVITY));
127 strcpy(ap->Ap_Name, "CONNECT");
128 g->Activityp= ap;
129 g->Activityp->Aptr= dup;
130
131 pthread_mutex_lock(&usrmut);
132 next= to_users;
133 to_users= this;
134
135 if (next)
136 next->previous= this;
137
138 count = 1;
139 pthread_mutex_unlock(&usrmut);
140
141 last_query_id= thdp->query_id;
142 return false;
143 } // end of user_init
144
145
SetHandler(ha_connect * hc)146 void user_connect::SetHandler(ha_connect *hc)
147 {
148 PDBUSER dup= (PDBUSER)g->Activityp->Aptr;
149 MYCAT *mc= (MYCAT*)dup->Catalog;
150 mc->SetHandler(hc);
151 }
152
153 /****************************************************************************/
154 /* Check whether we begin a new query and if so cleanup the previous one. */
155 /****************************************************************************/
CheckCleanup(bool force)156 bool user_connect::CheckCleanup(bool force)
157 {
158 if (thdp->query_id > last_query_id || force) {
159 size_t worksize = GetWorkSize();
160
161 PlugCleanup(g, true);
162
163 if (worksize != g->Sarea_Size) {
164 FreeSarea(g);
165 g->Saved_Size = g->Sarea_Size;
166
167 // Check whether the work area could be allocated
168 if (AllocSarea(g, worksize)) {
169 AllocSarea(g, g->Saved_Size);
170 SetWorkSize(g->Sarea_Size); // Was too big
171 } // endif sarea
172
173 } // endif worksize
174
175 PlugSubSet(g->Sarea, g->Sarea_Size);
176 g->Xchk = NULL;
177 g->Createas = false;
178 g->Alchecked = 0;
179 g->Mrr = 0;
180 g->More = 0;
181 g->Saved_Size = 0;
182 last_query_id= thdp->query_id;
183
184 if (trace(65) && !force)
185 printf("=====> Begin new query %llu\n", last_query_id);
186
187 return true;
188 } // endif query_id
189
190 return false;
191 } // end of CheckCleanup
192
193