1 /*
2    Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
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 
26 #include <ndb_global.h>
27 
28 #include "API.hpp"
29 
30 #include <signaldata/ScanTab.hpp>
31 
32 #include <NdbOut.hpp>
33 #include <NdbQueryOperationImpl.hpp>
34 
35 /***************************************************************************
36  * int  receiveSCAN_TABREF(NdbApiSignal* aSignal)
37  *
38  *  This means the scan could not be started, set status(s) to indicate
39  *  the failure
40  *
41  ****************************************************************************/
42 int
receiveSCAN_TABREF(const NdbApiSignal * aSignal)43 NdbTransaction::receiveSCAN_TABREF(const NdbApiSignal* aSignal){
44   const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr());
45 
46   if (checkState_TransId(&ref->transId1)) {
47     if (theScanningOp) {
48       theScanningOp->execCLOSE_SCAN_REP();
49       theScanningOp->setErrorCode(ref->errorCode);
50       if(!ref->closeNeeded){
51         return 0;
52       }
53 
54       /**
55        * Setup so that close_impl will actually perform a close
56        *   and not "close scan"-optimze it away
57        */
58       theScanningOp->m_conf_receivers_count++;
59       theScanningOp->m_conf_receivers[0] = theScanningOp->m_receivers[0];
60       theScanningOp->m_conf_receivers[0]->m_tcPtrI = ~0;
61 
62     } else {
63       assert (m_scanningQuery);
64       m_scanningQuery->execCLOSE_SCAN_REP(ref->errorCode, ref->closeNeeded);
65       if(!ref->closeNeeded){
66         return 0;
67       }
68     }
69     return 0;
70   } else {
71 #ifdef NDB_NO_DROPPED_SIGNAL
72     abort();
73 #endif
74   }
75 
76   return -1;
77 }
78 
79 /*****************************************************************************
80  * int  receiveSCAN_TABCONF(NdbApiSignal* aSignal)
81  *
82  * Receive SCAN_TABCONF
83  * If scanStatus == 0 there is more records to read. Since signals may be
84  * received in any order we have to go through the lists with saved signals
85  * and check if all expected signals are there so that we can start to
86  * execute them.
87  *
88  * If scanStatus > 0 this indicates that the scan is finished and there are
89  * no more data to be read.
90  *
91  *****************************************************************************/
92 int
receiveSCAN_TABCONF(const NdbApiSignal * aSignal,const Uint32 * ops,Uint32 len)93 NdbTransaction::receiveSCAN_TABCONF(const NdbApiSignal* aSignal,
94 				   const Uint32 * ops, Uint32 len)
95 {
96   const ScanTabConf * conf = CAST_CONSTPTR(ScanTabConf, aSignal->getDataPtr());
97 
98   if (checkState_TransId(&conf->transId1)) {
99 
100     /**
101      * If EndOfData is set, close the scan.
102      */
103     if (conf->requestInfo == ScanTabConf::EndOfData) {
104       if (theScanningOp) {
105         theScanningOp->execCLOSE_SCAN_REP();
106       } else {
107         assert (m_scanningQuery);
108         m_scanningQuery->execCLOSE_SCAN_REP(0, false);
109       }
110       return 1; // -> Finished
111     }
112 
113     int retVal = -1;
114     Uint32 words_per_op = theScanningOp ? 3 : 4;
115     for(Uint32 i = 0; i<len; i += words_per_op)
116     {
117       Uint32 ptrI = * ops++;
118       Uint32 tcPtrI = * ops++;
119       Uint32 opCount;
120       Uint32 totalLen;
121       if (words_per_op == 3)
122       {
123         Uint32 info = * ops++;
124         opCount  = ScanTabConf::getRows(info);
125         totalLen = ScanTabConf::getLength(info);
126       }
127       else
128       {
129         opCount = * ops++;
130         totalLen = * ops++;
131       }
132 
133       void * tPtr = theNdb->theImpl->int2void(ptrI);
134       assert(tPtr); // For now
135       NdbReceiver* tOp = NdbImpl::void2rec(tPtr);
136       if (tOp && tOp->checkMagicNumber())
137       {
138         // Check if this is a linked operation.
139         if (tOp->getType()==NdbReceiver::NDB_QUERY_OPERATION)
140         {
141           NdbQueryOperationImpl* queryOp = (NdbQueryOperationImpl*)tOp->m_owner;
142           assert (&queryOp->getQuery() == m_scanningQuery);
143 
144           if (queryOp->execSCAN_TABCONF(tcPtrI, opCount, totalLen, tOp))
145             retVal = 0; // We have result data, wakeup receiver
146         }
147         else
148         {
149           if (tcPtrI == RNIL && opCount == 0)
150           {
151             theScanningOp->receiver_completed(tOp);
152             retVal = 0;
153           }
154           else if (tOp->execSCANOPCONF(tcPtrI, totalLen, opCount))
155           {
156             theScanningOp->receiver_delivered(tOp);
157             retVal = 0;
158           }
159         }
160       }
161     } //for
162     return retVal;
163   } else {
164 #ifdef NDB_NO_DROPPED_SIGNAL
165     abort();
166 #endif
167   }
168 
169   return -1;
170 }
171