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     (void) 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