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
51extern pthread_mutex_t usrmut;
52
53/****************************************************************************/
54/* Initialize the user_connect static member. */
55/****************************************************************************/
56PCONNECT user_connect::to_users= NULL;
57
58/****************************************************************************/
59/* Get the work_size SESSION variable value . */
60/****************************************************************************/
61uint GetWorkSize(void);
62void SetWorkSize(uint);
63
64/* -------------------------- class user_connect -------------------------- */
65
66/****************************************************************************/
67/* Constructor. */
68/****************************************************************************/
69user_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/****************************************************************************/
87user_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/****************************************************************************/
97bool 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
147void 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/****************************************************************************/
157bool 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