1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include "SimBlockList.hpp"
26 #include <Emulator.hpp>
27 #include <SimulatedBlock.hpp>
28 #include <Cmvmi.hpp>
29 #include <Ndbfs.hpp>
30 #include <Dbacc.hpp>
31 #include <Dbdict.hpp>
32 #include <Dbdih.hpp>
33 #include <Dblqh.hpp>
34 #include <Dbspj.hpp>
35 #include <Dbtc.hpp>
36 #include <Dbtup.hpp>
37 #include <Ndbcntr.hpp>
38 #include <Qmgr.hpp>
39 #include <Trix.hpp>
40 #include <Backup.hpp>
41 #include <DbUtil.hpp>
42 #include <Suma.hpp>
43 #include <Dbtux.hpp>
44 #include <tsman.hpp>
45 #include <lgman.hpp>
46 #include <pgman.hpp>
47 #include <restore.hpp>
48 #include <Dbinfo.hpp>
49 #include <NdbEnv.h>
50 #include <LocalProxy.hpp>
51 #include <DblqhProxy.hpp>
52 #include <DbspjProxy.hpp>
53 #include <DbaccProxy.hpp>
54 #include <DbtupProxy.hpp>
55 #include <DbtuxProxy.hpp>
56 #include <BackupProxy.hpp>
57 #include <RestoreProxy.hpp>
58 #include <PgmanProxy.hpp>
59 #include <DbtcProxy.hpp>
60 #include <DbspjProxy.hpp>
61 #include <thrman.hpp>
62 #include <trpman.hpp>
63 #include <mt.hpp>
64 
65 #define JAM_FILE_ID 492
66 
67 
68 #ifndef VM_TRACE
69 #define NEW_BLOCK(B) new B
70 #else
71 enum SIMBLOCKLIST_DUMMY { A_VALUE = 0 };
72 
operator new(size_t sz,SIMBLOCKLIST_DUMMY dummy)73 void * operator new (size_t sz, SIMBLOCKLIST_DUMMY dummy){
74   char * tmp = (char *)malloc(sz);
75   if (!tmp)
76     abort();
77 
78 #ifndef NDB_PURIFY
79 #ifdef VM_TRACE
80   const int initValue = 0xf3;
81 #else
82   const int initValue = 0x0;
83 #endif
84 
85   const int p = (sz / 4096);
86   const int r = (sz % 4096);
87 
88   for(int i = 0; i<p; i++)
89     memset(tmp+(i*4096), initValue, 4096);
90 
91   if(r > 0)
92     memset(tmp+p*4096, initValue, r);
93 
94 #endif
95 
96   return tmp;
97 }
98 #define NEW_BLOCK(B) new(A_VALUE) B
99 #endif
100 
101 void
load(EmulatorData & data)102 SimBlockList::load(EmulatorData& data){
103   noOfBlocks = NO_OF_BLOCKS;
104   theList = new SimulatedBlock * [noOfBlocks];
105   if (!theList)
106   {
107     ERROR_SET(fatal, NDBD_EXIT_MEMALLOC,
108               "Failed to create the block list", "");
109   }
110 
111   Block_context ctx(*data.theConfiguration, *data.m_mem_manager);
112 
113   SimulatedBlock * fs = 0;
114   {
115     Uint32 dl;
116     const ndb_mgm_configuration_iterator * p =
117       ctx.m_config.getOwnConfigIterator();
118     if(p && !ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &dl) && dl){
119       fs = NEW_BLOCK(VoidFs)(ctx);
120     } else {
121       fs = NEW_BLOCK(Ndbfs)(ctx);
122     }
123   }
124 
125   const bool mtLqh = globalData.isNdbMtLqh;
126 
127   if (!mtLqh)
128     theList[0] = NEW_BLOCK(Pgman)(ctx);
129   else
130     theList[0] = NEW_BLOCK(PgmanProxy)(ctx);
131   theList[1]  = NEW_BLOCK(Lgman)(ctx);
132   theList[2]  = NEW_BLOCK(Tsman)(ctx);
133   if (!mtLqh)
134     theList[3]  = NEW_BLOCK(Dbacc)(ctx);
135   else
136     theList[3]  = NEW_BLOCK(DbaccProxy)(ctx);
137   theList[4]  = NEW_BLOCK(Cmvmi)(ctx);
138   theList[5]  = fs;
139   theList[6]  = NEW_BLOCK(Dbdict)(ctx);
140   theList[7]  = NEW_BLOCK(Dbdih)(ctx);
141   if (!mtLqh)
142     theList[8]  = NEW_BLOCK(Dblqh)(ctx);
143   else
144     theList[8]  = NEW_BLOCK(DblqhProxy)(ctx);
145   if (globalData.ndbMtTcThreads == 0)
146     theList[9]  = NEW_BLOCK(Dbtc)(ctx);
147   else
148     theList[9] = NEW_BLOCK(DbtcProxy)(ctx);
149   if (!mtLqh)
150     theList[10] = NEW_BLOCK(Dbtup)(ctx);
151   else
152     theList[10] = NEW_BLOCK(DbtupProxy)(ctx);
153   theList[11] = NEW_BLOCK(Ndbcntr)(ctx);
154   theList[12] = NEW_BLOCK(Qmgr)(ctx);
155   theList[13] = NEW_BLOCK(Trix)(ctx);
156   if (!mtLqh)
157     theList[14] = NEW_BLOCK(Backup)(ctx);
158   else
159     theList[14] = NEW_BLOCK(BackupProxy)(ctx);
160   theList[15] = NEW_BLOCK(DbUtil)(ctx);
161   theList[16] = NEW_BLOCK(Suma)(ctx);
162   if (!mtLqh)
163     theList[17] = NEW_BLOCK(Dbtux)(ctx);
164   else
165     theList[17] = NEW_BLOCK(DbtuxProxy)(ctx);
166   if (!mtLqh)
167     theList[18] = NEW_BLOCK(Restore)(ctx);
168   else
169     theList[18] = NEW_BLOCK(RestoreProxy)(ctx);
170   theList[19] = NEW_BLOCK(Dbinfo)(ctx);
171   if (globalData.ndbMtTcThreads == 0)
172     theList[20]  = NEW_BLOCK(Dbspj)(ctx);
173   else
174     theList[20]  = NEW_BLOCK(DbspjProxy)(ctx);
175   if (NdbIsMultiThreaded() == false)
176     theList[21] = NEW_BLOCK(Thrman)(ctx);
177   else
178     theList[21] = NEW_BLOCK(ThrmanProxy)(ctx);
179   if (NdbIsMultiThreaded() == false)
180     theList[22] = NEW_BLOCK(Trpman)(ctx);
181   else
182     theList[22] = NEW_BLOCK(TrpmanProxy)(ctx);
183   assert(NO_OF_BLOCKS == 23);
184 
185   // Check that all blocks could be created
186   for (int i = 0; i < noOfBlocks; i++)
187   {
188     if (!theList[i])
189     {
190       ERROR_SET(fatal, NDBD_EXIT_MEMALLOC,
191                 "Failed to create block", "");
192     }
193   }
194 
195   if (globalData.isNdbMt)
196   {
197     /**
198       This is where we bind blocks to their respective threads.
199       mt_init_thr_map binds the blocks to the two main threads,
200       the thread for Global blocks (thr = 0), and the thread
201       for Local blocks (thr = 1) and it puts CMVMI into the receiver
202       thread.
203 
204       For those blocks where we created proxies above the loadWorkers
205       function will map the instances of the block into the right
206       thread. mt_add_thr_map will be called for each of the block
207       instances.
208     */
209     mt_init_thr_map();
210     for (int i = 0; i < noOfBlocks; i++)
211       theList[i]->loadWorkers();
212     mt_finalize_thr_map();
213   }
214 }
215 
216 void
unload()217 SimBlockList::unload(){
218   if(theList != 0){
219     for(int i = 0; i<noOfBlocks; i++){
220       if(theList[i] != 0){
221 #ifdef VM_TRACE
222 	theList[i]->~SimulatedBlock();
223 	free(theList[i]);
224 #else
225         delete(theList[i]);
226 #endif
227 	theList[i] = 0;
228       }
229     }
230     delete [] theList;
231     theList    = 0;
232     noOfBlocks = 0;
233   }
234 }
235