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