1 /* Copyright (c) 2008, 2021, Oracle and/or its affiliates.
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, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
22 
23 #ifndef NDB_DBLQH_PROXY_HPP
24 #define NDB_DBLQH_PROXY_HPP
25 
26 #include <LocalProxy.hpp>
27 #include <signaldata/CreateTab.hpp>
28 #include <signaldata/LqhFrag.hpp>
29 #include <signaldata/TabCommit.hpp>
30 #include <signaldata/LCP.hpp>
31 #include <signaldata/GCP.hpp>
32 #include <signaldata/PrepDropTab.hpp>
33 #include <signaldata/DropTab.hpp>
34 #include <signaldata/AlterTab.hpp>
35 #include <signaldata/StartRec.hpp>
36 #include <signaldata/LqhTransReq.hpp>
37 #include <signaldata/LqhTransConf.hpp>
38 #include <signaldata/EmptyLcp.hpp>
39 
40 #define JAM_FILE_ID 445
41 
42 
43 class DblqhProxy : public LocalProxy {
44 public:
45   DblqhProxy(Block_context& ctx);
46   virtual ~DblqhProxy();
47   BLOCK_DEFINES(DblqhProxy);
48 
49 protected:
50   virtual SimulatedBlock* newWorker(Uint32 instanceNo);
51 
52   // system info
53   Uint32 c_tableRecSize;
54   Uint8* c_tableRec;    // bool => table exists
55 
56   // GSN_NDB_STTOR
57   virtual void callNDB_STTOR(Signal*);
58   virtual void callREAD_CONFIG_REQ(Signal*);
59 
60   // GSN_CREATE_TAB_REQ
61   struct Ss_CREATE_TAB_REQ : SsParallel {
62     CreateTabReq m_req;
63     Uint32 m_lqhConnectPtr[MaxWorkers];
Ss_CREATE_TAB_REQDblqhProxy::Ss_CREATE_TAB_REQ64     Ss_CREATE_TAB_REQ() {
65       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendCREATE_TAB_REQ;
66       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendCREATE_TAB_CONF;
67     }
68     enum { poolSize = 1 };
poolDblqhProxy::Ss_CREATE_TAB_REQ69     static SsPool<Ss_CREATE_TAB_REQ>& pool(LocalProxy* proxy) {
70       return ((DblqhProxy*)proxy)->c_ss_CREATE_TAB_REQ;
71     }
72   };
73   SsPool<Ss_CREATE_TAB_REQ> c_ss_CREATE_TAB_REQ;
74   void execCREATE_TAB_REQ(Signal*);
75   void sendCREATE_TAB_REQ(Signal*, Uint32 ssId, SectionHandle*);
76   void execCREATE_TAB_CONF(Signal*);
77   void execCREATE_TAB_REF(Signal*);
78   void sendCREATE_TAB_CONF(Signal*, Uint32 ssId);
79 
80   // GSN_LQHADDATTREQ [ sub-op ]
81   struct Ss_LQHADDATTREQ : SsParallel {
82     LqhAddAttrReq m_req;
83     Uint32 m_reqlength;
Ss_LQHADDATTREQDblqhProxy::Ss_LQHADDATTREQ84     Ss_LQHADDATTREQ() {
85       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendLQHADDATTREQ;
86       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendLQHADDATTCONF;
87     }
88     enum { poolSize = 1 };
poolDblqhProxy::Ss_LQHADDATTREQ89     static SsPool<Ss_LQHADDATTREQ>& pool(LocalProxy* proxy) {
90       return ((DblqhProxy*)proxy)->c_ss_LQHADDATTREQ;
91     }
92   };
93   SsPool<Ss_LQHADDATTREQ> c_ss_LQHADDATTREQ;
94   void execLQHADDATTREQ(Signal*);
95   void sendLQHADDATTREQ(Signal*, Uint32 ssId, SectionHandle*);
96   void execLQHADDATTCONF(Signal*);
97   void execLQHADDATTREF(Signal*);
98   void sendLQHADDATTCONF(Signal*, Uint32 ssId);
99 
100   // GSN_LQHFRAGREQ [ pass-through ]
101   void execLQHFRAGREQ(Signal*);
102 
103   // GSN_TAB_COMMITREQ [ sub-op ]
104   struct Ss_TAB_COMMITREQ : SsParallel {
105     TabCommitReq m_req;
Ss_TAB_COMMITREQDblqhProxy::Ss_TAB_COMMITREQ106     Ss_TAB_COMMITREQ() {
107       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendTAB_COMMITREQ;
108       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendTAB_COMMITCONF;
109     }
110     enum { poolSize = 1 };
poolDblqhProxy::Ss_TAB_COMMITREQ111     static SsPool<Ss_TAB_COMMITREQ>& pool(LocalProxy* proxy) {
112       return ((DblqhProxy*)proxy)->c_ss_TAB_COMMITREQ;
113     }
114   };
115   SsPool<Ss_TAB_COMMITREQ> c_ss_TAB_COMMITREQ;
116   void execTAB_COMMITREQ(Signal*);
117   void sendTAB_COMMITREQ(Signal*, Uint32 ssId, SectionHandle*);
118   void execTAB_COMMITCONF(Signal*);
119   void execTAB_COMMITREF(Signal*);
120   void sendTAB_COMMITCONF(Signal*, Uint32 ssId);
121 
122   // GSN_GCP_SAVEREQ
123   struct Ss_GCP_SAVEREQ : SsParallel {
nameDblqhProxy::Ss_GCP_SAVEREQ124     static const char* name() { return "GCP_SAVEREQ"; }
125     GCPSaveReq m_req;
Ss_GCP_SAVEREQDblqhProxy::Ss_GCP_SAVEREQ126     Ss_GCP_SAVEREQ() {
127       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendGCP_SAVEREQ;
128       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendGCP_SAVECONF;
129     }
130     enum { poolSize = 1 };
poolDblqhProxy::Ss_GCP_SAVEREQ131     static SsPool<Ss_GCP_SAVEREQ>& pool(LocalProxy* proxy) {
132       return ((DblqhProxy*)proxy)->c_ss_GCP_SAVEREQ;
133     }
134   };
135   SsPool<Ss_GCP_SAVEREQ> c_ss_GCP_SAVEREQ;
getSsId(const GCPSaveReq * req)136   Uint32 getSsId(const GCPSaveReq* req) {
137     return SsIdBase | (req->gci & 0xFFFF);
138   }
getSsId(const GCPSaveConf * conf)139   Uint32 getSsId(const GCPSaveConf* conf) {
140     return SsIdBase | (conf->gci & 0xFFFF);
141   }
getSsId(const GCPSaveRef * ref)142   Uint32 getSsId(const GCPSaveRef* ref) {
143     return SsIdBase | (ref->gci & 0xFFFF);
144   }
145   void execGCP_SAVEREQ(Signal*);
146   void sendGCP_SAVEREQ(Signal*, Uint32 ssId, SectionHandle*);
147   void execGCP_SAVECONF(Signal*);
148   void execGCP_SAVEREF(Signal*);
149   void sendGCP_SAVECONF(Signal*, Uint32 ssId);
150 
151   // GSN_SUB_GCP_COMPLETE_REP
152   void execSUB_GCP_COMPLETE_REP(Signal*);
153 
154   // GSN_PREP_DROP_TAB_REQ
155   struct Ss_PREP_DROP_TAB_REQ : SsParallel {
156     PrepDropTabReq m_req;
Ss_PREP_DROP_TAB_REQDblqhProxy::Ss_PREP_DROP_TAB_REQ157     Ss_PREP_DROP_TAB_REQ() {
158       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendPREP_DROP_TAB_REQ;
159       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendPREP_DROP_TAB_CONF;
160     }
161     enum { poolSize = 1 };
poolDblqhProxy::Ss_PREP_DROP_TAB_REQ162     static SsPool<Ss_PREP_DROP_TAB_REQ>& pool(LocalProxy* proxy) {
163       return ((DblqhProxy*)proxy)->c_ss_PREP_DROP_TAB_REQ;
164     }
165   };
166   SsPool<Ss_PREP_DROP_TAB_REQ> c_ss_PREP_DROP_TAB_REQ;
getSsId(const PrepDropTabReq * req)167   Uint32 getSsId(const PrepDropTabReq* req) {
168     return SsIdBase | req->tableId;
169   }
getSsId(const PrepDropTabConf * conf)170   Uint32 getSsId(const PrepDropTabConf* conf) {
171     return SsIdBase | conf->tableId;
172   }
getSsId(const PrepDropTabRef * ref)173   Uint32 getSsId(const PrepDropTabRef* ref) {
174     return SsIdBase | ref->tableId;
175   }
176   void execPREP_DROP_TAB_REQ(Signal*);
177   void sendPREP_DROP_TAB_REQ(Signal*, Uint32 ssId, SectionHandle*);
178   void execPREP_DROP_TAB_CONF(Signal*);
179   void execPREP_DROP_TAB_REF(Signal*);
180   void sendPREP_DROP_TAB_CONF(Signal*, Uint32 ssId);
181 
182   // GSN_DROP_TAB_REQ
183   struct Ss_DROP_TAB_REQ : SsParallel {
184     DropTabReq m_req;
Ss_DROP_TAB_REQDblqhProxy::Ss_DROP_TAB_REQ185     Ss_DROP_TAB_REQ() {
186       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendDROP_TAB_REQ;
187       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendDROP_TAB_CONF;
188     }
189     enum { poolSize = 1 };
poolDblqhProxy::Ss_DROP_TAB_REQ190     static SsPool<Ss_DROP_TAB_REQ>& pool(LocalProxy* proxy) {
191       return ((DblqhProxy*)proxy)->c_ss_DROP_TAB_REQ;
192     }
193   };
194   SsPool<Ss_DROP_TAB_REQ> c_ss_DROP_TAB_REQ;
getSsId(const DropTabReq * req)195   Uint32 getSsId(const DropTabReq* req) {
196     return SsIdBase | req->tableId;
197   }
getSsId(const DropTabConf * conf)198   Uint32 getSsId(const DropTabConf* conf) {
199     return SsIdBase | conf->tableId;
200   }
getSsId(const DropTabRef * ref)201   Uint32 getSsId(const DropTabRef* ref) {
202     return SsIdBase | ref->tableId;
203   }
204   void execDROP_TAB_REQ(Signal*);
205   void sendDROP_TAB_REQ(Signal*, Uint32 ssId, SectionHandle*);
206   void execDROP_TAB_CONF(Signal*);
207   void execDROP_TAB_REF(Signal*);
208   void sendDROP_TAB_CONF(Signal*, Uint32 ssId);
209 
210   // GSN_ALTER_TAB_REQ
211   struct Ss_ALTER_TAB_REQ : SsParallel {
212     AlterTabReq m_req;
Ss_ALTER_TAB_REQDblqhProxy::Ss_ALTER_TAB_REQ213     Ss_ALTER_TAB_REQ() {
214       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendALTER_TAB_REQ;
215       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendALTER_TAB_CONF;
216     }
217     enum { poolSize = 1 };
poolDblqhProxy::Ss_ALTER_TAB_REQ218     static SsPool<Ss_ALTER_TAB_REQ>& pool(LocalProxy* proxy) {
219       return ((DblqhProxy*)proxy)->c_ss_ALTER_TAB_REQ;
220     }
221   };
222   SsPool<Ss_ALTER_TAB_REQ> c_ss_ALTER_TAB_REQ;
getSsId(const AlterTabReq * req)223   Uint32 getSsId(const AlterTabReq* req) {
224     return SsIdBase | req->tableId;
225   }
getSsId(const AlterTabConf * conf)226   Uint32 getSsId(const AlterTabConf* conf) {
227     return conf->senderData;
228   }
getSsId(const AlterTabRef * ref)229   Uint32 getSsId(const AlterTabRef* ref) {
230     return ref->senderData;
231   }
232   void execALTER_TAB_REQ(Signal*);
233   void sendALTER_TAB_REQ(Signal*, Uint32 ssId, SectionHandle*);
234   void execALTER_TAB_CONF(Signal*);
235   void execALTER_TAB_REF(Signal*);
236   void sendALTER_TAB_CONF(Signal*, Uint32 ssId);
237 
238   /**
239    * GSN_START_FRAGREQ needs to be serialized wrt START_RECREQ
240    *   so send it via proxy, even if DIH knows where to send it...
241    */
242   void execSTART_FRAGREQ(Signal*);
243 
244   // GSN_START_RECREQ
245   struct Ss_START_RECREQ : SsParallel {
246     /*
247      * The proxy is also proxy for signals from workers to global
248      * blocks LGMAN, TSMAN.  These are run (sequentially) using
249      * the sub-op START_RECREQ_2.
250      */
nameDblqhProxy::Ss_START_RECREQ251     static const char* name() { return "START_RECREQ"; }
252     StartRecReq m_req;
253     Uint32 phaseToSend;
254     Uint32 restoreFragCompletedCount;
255     Uint32 undoDDCompletedCount;
256     Uint32 execREDOLogCompletedCount;
257     // pointers to START_RECREQ_2 for LGMAN, TSMAN
258     enum { m_req2cnt = 2 };
259     struct {
260       Uint32 m_blockNo;
261       Uint32 m_ssId;
262     } m_req2[m_req2cnt];
Ss_START_RECREQDblqhProxy::Ss_START_RECREQ263     Ss_START_RECREQ() {
264       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendSTART_RECREQ;
265       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendSTART_RECCONF;
266       m_req2[0].m_blockNo = LGMAN;
267       m_req2[1].m_blockNo = TSMAN;
268     }
269     enum { poolSize = 1 };
poolDblqhProxy::Ss_START_RECREQ270     static SsPool<Ss_START_RECREQ>& pool(LocalProxy* proxy) {
271       return ((DblqhProxy*)proxy)->c_ss_START_RECREQ;
272     }
273   };
274   SsPool<Ss_START_RECREQ> c_ss_START_RECREQ;
275   void execSTART_RECREQ(Signal*);
276   void sendSTART_RECREQ(Signal*, Uint32 ssId, SectionHandle*);
277   void execSTART_RECCONF(Signal*);
278   void execLOCAL_RECOVERY_COMP_REP(Signal*);
279   void sendSTART_RECCONF(Signal*, Uint32 ssId);
280 
281   // GSN_START_RECREQ_2 [ sub-op, fictional gsn ]
282   struct Ss_START_RECREQ_2 : SsParallel {
nameDblqhProxy::Ss_START_RECREQ_2283     static const char* name() { return "START_RECREQ_2"; }
284     struct Req {
285       enum { SignalLength = 2 };
286       Uint32 lcpId;
287       Uint32 proxyBlockNo;
288     };
289     // senderData is unnecessary as signal is unique per proxyBlockNo
290     struct Conf {
291       enum { SignalLength = 1 };
292       Uint32 senderRef;
293     };
294     Req m_req;
295     Conf m_conf;
Ss_START_RECREQ_2DblqhProxy::Ss_START_RECREQ_2296     Ss_START_RECREQ_2() {
297       // reversed sendREQ/sendCONF
298       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendSTART_RECCONF_2;
299       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendSTART_RECREQ_2;
300     }
301     enum { poolSize = 2 };
poolDblqhProxy::Ss_START_RECREQ_2302     static SsPool<Ss_START_RECREQ_2>& pool(LocalProxy* proxy) {
303       return ((DblqhProxy*)proxy)->c_ss_START_RECREQ_2;
304     }
305   };
306   SsPool<Ss_START_RECREQ_2> c_ss_START_RECREQ_2;
getSsId(const Ss_START_RECREQ_2::Req * req)307   Uint32 getSsId(const Ss_START_RECREQ_2::Req* req) {
308     return SsIdBase | req->proxyBlockNo;
309   }
getSsId(const Ss_START_RECREQ_2::Conf * conf)310   Uint32 getSsId(const Ss_START_RECREQ_2::Conf* conf) {
311     return SsIdBase | refToBlock(conf->senderRef);
312   }
313   void execSTART_RECREQ_2(Signal*);
314   void sendSTART_RECREQ_2(Signal*, Uint32 ssId);
315   void execSTART_RECCONF_2(Signal*);
316   void sendSTART_RECCONF_2(Signal*, Uint32 ssId, SectionHandle*);
317 
318   // GSN_LQH_TRANSREQ
319   struct Ss_LQH_TRANSREQ : SsParallel {
nameDblqhProxy::Ss_LQH_TRANSREQ320     static const char* name() { return "LQH_TRANSREQ"; }
321     /**
322      * Is this entry valid, or has it been made obsolete by
323      *   a new LQH_TRANSREQ (i.e a new TC-failure)
324      */
325     bool m_valid;
326     Uint32 m_maxInstanceId;
327     LqhTransReq m_req;
328     LqhTransConf m_conf; // latest conf
Ss_LQH_TRANSREQDblqhProxy::Ss_LQH_TRANSREQ329     Ss_LQH_TRANSREQ() {
330       m_valid = true;
331       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendLQH_TRANSREQ;
332       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendLQH_TRANSCONF;
333     }
334     enum { poolSize = MAX_NDB_NODES };
poolDblqhProxy::Ss_LQH_TRANSREQ335     static SsPool<Ss_LQH_TRANSREQ>& pool(LocalProxy* proxy) {
336       return ((DblqhProxy*)proxy)->c_ss_LQH_TRANSREQ;
337     }
338   };
339   SsPool<Ss_LQH_TRANSREQ> c_ss_LQH_TRANSREQ;
340   void execLQH_TRANSREQ(Signal*);
341   void sendLQH_TRANSREQ(Signal*, Uint32 ssId, SectionHandle*);
342   void execLQH_TRANSCONF(Signal*);
343   void sendLQH_TRANSCONF(Signal*, Uint32 ssId);
344 
345   // GSN_EXEC_SR_1 [ fictional gsn ]
346   struct Ss_EXEC_SR_1 : SsParallel {
347     /*
348      * Handle EXEC_SRREQ and EXEC_SRCONF.  These are broadcast
349      * signals (not REQ/CONF).  EXEC_SR_1 receives one signal and
350      * sends it to its workers.  EXEC_SR_2 waits for signal from
351      * all workers and broadcasts it to all nodes.  These are
352      * required to handle mixed versions (non-mt, mt-lqh-1,2,4).
353      */
nameDblqhProxy::Ss_EXEC_SR_1354     static const char* name() { return "EXEC_SR_1"; }
355     struct Sig {
356       enum { SignalLength = 1 };
357       Uint32 nodeId;
358     };
359     GlobalSignalNumber m_gsn;
360     Sig m_sig;
Ss_EXEC_SR_1DblqhProxy::Ss_EXEC_SR_1361     Ss_EXEC_SR_1() {
362       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendEXEC_SR_1;
363       m_sendCONF = (SsFUNCREP)0;
364       m_gsn = 0;
365     };
366     enum { poolSize = 1 };
poolDblqhProxy::Ss_EXEC_SR_1367     static SsPool<Ss_EXEC_SR_1>& pool(LocalProxy* proxy) {
368       return ((DblqhProxy*)proxy)->c_ss_EXEC_SR_1;
369     }
370   };
371   SsPool<Ss_EXEC_SR_1> c_ss_EXEC_SR_1;
getSsId(const Ss_EXEC_SR_1::Sig * sig)372   Uint32 getSsId(const Ss_EXEC_SR_1::Sig* sig) {
373     return SsIdBase | refToNode(sig->nodeId);
374   };
375   void execEXEC_SRREQ(Signal*);
376   void execEXEC_SRCONF(Signal*);
377   void execEXEC_SR_1(Signal*, GlobalSignalNumber gsn);
378   void sendEXEC_SR_1(Signal*, Uint32 ssId, SectionHandle*);
379 
380   // GSN_EXEC_SR_2 [ fictional gsn ]
381   struct Ss_EXEC_SR_2 : SsParallel {
nameDblqhProxy::Ss_EXEC_SR_2382     static const char* name() { return "EXEC_SR_2"; }
383     struct Sig {
384       enum { SignalLength = 1 + NdbNodeBitmask::Size };
385       Uint32 nodeId;
386       Uint32 sr_nodes[NdbNodeBitmask::Size]; // local signal so ok to add
387     };
388     GlobalSignalNumber m_gsn;
389     Uint32 m_sigcount;
390     Sig m_sig; // all signals must be identical
Ss_EXEC_SR_2DblqhProxy::Ss_EXEC_SR_2391     Ss_EXEC_SR_2() {
392       // reversed roles
393       m_sendREQ = (SsFUNCREQ)0;
394       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendEXEC_SR_2;
395       m_gsn = 0;
396       m_sigcount = 0;
397     };
398     enum { poolSize = 1 };
poolDblqhProxy::Ss_EXEC_SR_2399     static SsPool<Ss_EXEC_SR_2>& pool(LocalProxy* proxy) {
400       return ((DblqhProxy*)proxy)->c_ss_EXEC_SR_2;
401     }
402   };
403   SsPool<Ss_EXEC_SR_2> c_ss_EXEC_SR_2;
getSsId(const Ss_EXEC_SR_2::Sig * sig)404   Uint32 getSsId(const Ss_EXEC_SR_2::Sig* sig) {
405     return SsIdBase | refToNode(sig->nodeId);
406   };
407   void execEXEC_SR_2(Signal*, GlobalSignalNumber gsn);
408   void sendEXEC_SR_2(Signal*, Uint32 ssId);
409 
410   /**
411    * GSN_EXEC_FRAGREQ & GSN_EXEC_FRAGCONF needs to
412    *   be passed via proxy for correct serialization
413    *   wrt to GSN_EXEC_SRREQ & GSN_EXEC_SRCONF
414    */
415   void execEXEC_FRAGREQ(Signal*);
416   void execEXEC_FRAGCONF(Signal*);
417 
418   // GSN_DROP_FRAG_REQ
419   struct Ss_DROP_FRAG_REQ : SsParallel {
420     DropFragReq m_req;
Ss_DROP_FRAG_REQDblqhProxy::Ss_DROP_FRAG_REQ421     Ss_DROP_FRAG_REQ() {
422       m_sendREQ = (SsFUNCREQ)&DblqhProxy::sendDROP_FRAG_REQ;
423       m_sendCONF = (SsFUNCREP)&DblqhProxy::sendDROP_FRAG_CONF;
424     }
425     enum { poolSize = 1 };
poolDblqhProxy::Ss_DROP_FRAG_REQ426     static SsPool<Ss_DROP_FRAG_REQ>& pool(LocalProxy* proxy) {
427       return ((DblqhProxy*)proxy)->c_ss_DROP_FRAG_REQ;
428     }
429   };
430   SsPool<Ss_DROP_FRAG_REQ> c_ss_DROP_FRAG_REQ;
getSsId(const DropFragReq * req)431   Uint32 getSsId(const DropFragReq* req) {
432     return SsIdBase | (req->tableId ^ req->fragId);
433   }
getSsId(const DropFragConf * conf)434   Uint32 getSsId(const DropFragConf* conf) {
435     return SsIdBase | (conf->tableId ^ conf->fragId);
436   }
getSsId(const DropFragRef * ref)437   Uint32 getSsId(const DropFragRef* ref) {
438     return SsIdBase | (ref->tableId ^ ref->fragId);
439   }
440   void execDROP_FRAG_REQ(Signal*);
441   void sendDROP_FRAG_REQ(Signal*, Uint32 ssId, SectionHandle*);
442   void execDROP_FRAG_CONF(Signal*);
443   void execDROP_FRAG_REF(Signal*);
444   void sendDROP_FRAG_CONF(Signal*, Uint32 ssId);
445 
446   // LCP handling
447   void execEMPTY_LCP_REQ(Signal*);
448   void execLCP_FRAG_ORD(Signal*);
449   void execLCP_FRAG_REP(Signal*);
450   void execEND_LCPCONF(Signal*);
451   void execLCP_COMPLETE_REP(Signal*);
452 
453   struct LcpRecord {
454     enum {
455       L_IDLE         = 0,
456       L_RUNNING      = 1,
457       L_COMPLETING_1 = 2,
458       L_COMPLETING_2 = 3,
459       L_COMPLETING_3 = 4
460     } m_state;
461     Uint32 m_lcpId;
462     Uint32 m_keepGci;
463     Uint32 m_lcp_frag_ord_cnt;     // No of LCP_FRAG_ORD received
464     Uint32 m_lcp_frag_rep_cnt;     // No of LCP_FRAG_REP sent
465     Uint32 m_complete_outstanding; // Outstanding END_LCPREQ
466     NdbNodeBitmask m_empty_lcp_req;// Nodes waiting for EMPTY_LCP_CONF
467     LcpFragOrd m_last_lcp_frag_ord;// Last received LCP_FRAG_ORD
468     bool m_lastFragmentFlag;
469 
LcpRecordDblqhProxy::LcpRecord470     LcpRecord(){
471       m_state = L_IDLE;
472       m_lcpId = 0;
473       m_lcp_frag_ord_cnt = 0;
474       m_lcp_frag_rep_cnt = 0;
475       m_lastFragmentFlag = false;
476     };
477   };
478   LcpRecord c_lcpRecord;
479   Uint32 getNoOfOutstanding(const LcpRecord&) const;
480   void completeLCP_1(Signal* signal);
481   void completeLCP_2(Signal* signal);
482   void completeLCP_3(Signal* signal);
483   void sendLCP_COMPLETE_REP(Signal*);
484 
485   void checkSendEMPTY_LCP_CONF_impl(Signal* signal);
checkSendEMPTY_LCP_CONF(Signal * signal)486   void checkSendEMPTY_LCP_CONF(Signal* signal)
487   {
488     if (c_lcpRecord.m_empty_lcp_req.isclear())
489       return;
490     checkSendEMPTY_LCP_CONF_impl(signal);
491   }
492 };
493 
494 
495 #undef JAM_FILE_ID
496 
497 #endif
498