1 /* Copyright (c) 2003-2008 MySQL AB
2 Use is subject to license terms
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 as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17 #define DBTUP_C
18 #define DBTUP_ABORT_CPP
19 #include "Dbtup.hpp"
20 #include <RefConvert.hpp>
21 #include <ndb_limits.h>
22 #include <pc.hpp>
23
freeAllAttrBuffers(Operationrec * const regOperPtr)24 void Dbtup::freeAllAttrBuffers(Operationrec* const regOperPtr)
25 {
26 if (regOperPtr->storedProcedureId == RNIL) {
27 jam();
28 freeAttrinbufrec(regOperPtr->firstAttrinbufrec);
29 } else {
30 jam();
31 StoredProcPtr storedPtr;
32 c_storedProcPool.getPtr(storedPtr, (Uint32)regOperPtr->storedProcedureId);
33 ndbrequire(storedPtr.p->storedCode == ZSCAN_PROCEDURE);
34 storedPtr.p->storedCounter--;
35 regOperPtr->storedProcedureId = ZNIL;
36 }//if
37 regOperPtr->firstAttrinbufrec = RNIL;
38 regOperPtr->lastAttrinbufrec = RNIL;
39 regOperPtr->m_any_value = 0;
40 }//Dbtup::freeAllAttrBuffers()
41
freeAttrinbufrec(Uint32 anAttrBuf)42 void Dbtup::freeAttrinbufrec(Uint32 anAttrBuf)
43 {
44 Uint32 Ttemp;
45 AttrbufrecPtr localAttrBufPtr;
46 Uint32 RnoFree = cnoFreeAttrbufrec;
47 localAttrBufPtr.i = anAttrBuf;
48 while (localAttrBufPtr.i != RNIL) {
49 jam();
50 ptrCheckGuard(localAttrBufPtr, cnoOfAttrbufrec, attrbufrec);
51 Ttemp = localAttrBufPtr.p->attrbuf[ZBUF_NEXT];
52 localAttrBufPtr.p->attrbuf[ZBUF_NEXT] = cfirstfreeAttrbufrec;
53 cfirstfreeAttrbufrec = localAttrBufPtr.i;
54 localAttrBufPtr.i = Ttemp;
55 RnoFree++;
56 }//if
57 cnoFreeAttrbufrec = RnoFree;
58 }//Dbtup::freeAttrinbufrec()
59
60 /**
61 * Abort abort this operation and all after (nextActiveOp's)
62 */
execTUP_ABORTREQ(Signal * signal)63 void Dbtup::execTUP_ABORTREQ(Signal* signal)
64 {
65 jamEntry();
66 do_tup_abortreq(signal, 0);
67 }
68
do_tup_abortreq(Signal * signal,Uint32 flags)69 void Dbtup::do_tup_abortreq(Signal* signal, Uint32 flags)
70 {
71 OperationrecPtr regOperPtr;
72 FragrecordPtr regFragPtr;
73 TablerecPtr regTabPtr;
74
75 regOperPtr.i = signal->theData[0];
76 c_operation_pool.getPtr(regOperPtr);
77 TransState trans_state= get_trans_state(regOperPtr.p);
78 ndbrequire((trans_state == TRANS_STARTED) ||
79 (trans_state == TRANS_TOO_MUCH_AI) ||
80 (trans_state == TRANS_ERROR_WAIT_TUPKEYREQ) ||
81 (trans_state == TRANS_IDLE));
82 if (regOperPtr.p->op_struct.op_type == ZREAD) {
83 jam();
84 freeAllAttrBuffers(regOperPtr.p);
85 initOpConnection(regOperPtr.p);
86 return;
87 }//if
88
89 regFragPtr.i = regOperPtr.p->fragmentPtr;
90 ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
91
92 regTabPtr.i = regFragPtr.p->fragTableId;
93 ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
94
95 if (get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
96 {
97 jam();
98 if (!regTabPtr.p->tuxCustomTriggers.isEmpty() &&
99 (flags & ZSKIP_TUX_TRIGGERS) == 0)
100 executeTuxAbortTriggers(signal,
101 regOperPtr.p,
102 regFragPtr.p,
103 regTabPtr.p);
104
105 OperationrecPtr loopOpPtr;
106 loopOpPtr.i = regOperPtr.p->nextActiveOp;
107 while (loopOpPtr.i != RNIL) {
108 jam();
109 c_operation_pool.getPtr(loopOpPtr);
110 if (get_tuple_state(loopOpPtr.p) != TUPLE_ALREADY_ABORTED &&
111 !regTabPtr.p->tuxCustomTriggers.isEmpty() &&
112 (flags & ZSKIP_TUX_TRIGGERS) == 0) {
113 jam();
114 executeTuxAbortTriggers(signal,
115 loopOpPtr.p,
116 regFragPtr.p,
117 regTabPtr.p);
118 }
119 set_tuple_state(loopOpPtr.p, TUPLE_ALREADY_ABORTED);
120 loopOpPtr.i = loopOpPtr.p->nextActiveOp;
121 }
122 }
123
124 PagePtr page;
125 Tuple_header *tuple_ptr= (Tuple_header*)
126 get_ptr(&page, ®OperPtr.p->m_tuple_location, regTabPtr.p);
127
128 Uint32 bits= tuple_ptr->m_header_bits;
129 if(regOperPtr.p->op_struct.op_type != ZDELETE)
130 {
131 Tuple_header *copy= (Tuple_header*)
132 c_undo_buffer.get_ptr(®OperPtr.p->m_copy_tuple_location);
133
134 if(regOperPtr.p->op_struct.m_disk_preallocated)
135 {
136 jam();
137 Local_key key;
138 memcpy(&key, copy->get_disk_ref_ptr(regTabPtr.p), sizeof(key));
139 disk_page_abort_prealloc(signal, regFragPtr.p, &key, key.m_page_idx);
140 }
141
142
143 Uint32 copy_bits= copy->m_header_bits;
144 if(! (bits & Tuple_header::ALLOC))
145 {
146 if(copy_bits & Tuple_header::MM_GROWN)
147 {
148 if (0) ndbout_c("abort grow");
149 Ptr<Page> vpage;
150 Uint32 idx= regOperPtr.p->m_tuple_location.m_page_idx;
151 Uint32 mm_vars= regTabPtr.p->m_attributes[MM].m_no_of_varsize;
152 Uint32 *var_part;
153
154 ndbassert(tuple_ptr->m_header_bits & Tuple_header::CHAINED_ROW);
155
156 Var_part_ref *ref = tuple_ptr->get_var_part_ref_ptr(regTabPtr.p);
157
158 Local_key tmp;
159 ref->copyout(&tmp);
160
161 idx= tmp.m_page_idx;
162 var_part= get_ptr(&vpage, *ref);
163 Var_page* pageP = (Var_page*)vpage.p;
164 Uint32 len= pageP->get_entry_len(idx) & ~Var_page::CHAIN;
165 Uint32 sz = ((((mm_vars + 1) << 1) + (((Uint16*)var_part)[mm_vars]) + 3)>> 2);
166 ndbassert(sz <= len);
167 pageP->shrink_entry(idx, sz);
168 update_free_page_list(regFragPtr.p, vpage);
169 }
170 else if(bits & Tuple_header::MM_SHRINK)
171 {
172 if (0) ndbout_c("abort shrink");
173 }
174 }
175 else if (regOperPtr.p->is_first_operation() &&
176 regOperPtr.p->is_last_operation())
177 {
178 /**
179 * Aborting last operation that performed ALLOC
180 */
181 tuple_ptr->m_header_bits &= ~(Uint32)Tuple_header::ALLOC;
182 tuple_ptr->m_header_bits |= Tuple_header::FREED;
183 }
184 }
185 else if (regOperPtr.p->is_first_operation() &&
186 regOperPtr.p->is_last_operation())
187 {
188 if (bits & Tuple_header::ALLOC)
189 {
190 tuple_ptr->m_header_bits &= ~(Uint32)Tuple_header::ALLOC;
191 tuple_ptr->m_header_bits |= Tuple_header::FREED;
192 }
193 }
194
195 if(regOperPtr.p->is_first_operation() && regOperPtr.p->is_last_operation())
196 {
197 if (regOperPtr.p->m_undo_buffer_space)
198 c_lgman->free_log_space(regFragPtr.p->m_logfile_group_id,
199 regOperPtr.p->m_undo_buffer_space);
200 }
201
202 removeActiveOpList(regOperPtr.p, tuple_ptr);
203 initOpConnection(regOperPtr.p);
204 }
205
206 /* **************************************************************** */
207 /* ********************** TRANSACTION ERROR MODULE **************** */
208 /* **************************************************************** */
TUPKEY_abort(Signal * signal,int error_type)209 int Dbtup::TUPKEY_abort(Signal* signal, int error_type)
210 {
211 switch(error_type) {
212 case 1:
213 //tmupdate_alloc_error:
214 terrorCode= ZMEM_NOMEM_ERROR;
215 jam();
216 break;
217
218 case 15:
219 jam();
220 terrorCode = ZREGISTER_INIT_ERROR;
221 break;
222
223 case 16:
224 jam();
225 terrorCode = ZTRY_TO_UPDATE_ERROR;
226 break;
227
228 case 17:
229 jam();
230 terrorCode = ZNO_ILLEGAL_NULL_ATTR;
231 break;
232
233 case 19:
234 jam();
235 terrorCode = ZTRY_TO_UPDATE_ERROR;
236 break;
237
238 case 20:
239 jam();
240 terrorCode = ZREGISTER_INIT_ERROR;
241 break;
242
243 case 22:
244 jam();
245 terrorCode = ZTOTAL_LEN_ERROR;
246 break;
247
248 case 23:
249 jam();
250 terrorCode = ZREGISTER_INIT_ERROR;
251 break;
252
253 case 24:
254 jam();
255 terrorCode = ZREGISTER_INIT_ERROR;
256 break;
257
258 case 26:
259 jam();
260 terrorCode = ZREGISTER_INIT_ERROR;
261 break;
262
263 case 27:
264 jam();
265 terrorCode = ZREGISTER_INIT_ERROR;
266 break;
267
268 case 28:
269 jam();
270 terrorCode = ZREGISTER_INIT_ERROR;
271 break;
272
273 case 29:
274 jam();
275 break;
276
277 case 30:
278 jam();
279 terrorCode = ZCALL_ERROR;
280 break;
281
282 case 31:
283 jam();
284 terrorCode = ZSTACK_OVERFLOW_ERROR;
285 break;
286
287 case 32:
288 jam();
289 terrorCode = ZSTACK_UNDERFLOW_ERROR;
290 break;
291
292 case 33:
293 jam();
294 terrorCode = ZNO_INSTRUCTION_ERROR;
295 break;
296
297 case 34:
298 jam();
299 terrorCode = ZOUTSIDE_OF_PROGRAM_ERROR;
300 break;
301
302 case 35:
303 jam();
304 terrorCode = ZTOO_MANY_INSTRUCTIONS_ERROR;
305 break;
306
307 case 38:
308 jam();
309 terrorCode = ZTEMPORARY_RESOURCE_FAILURE;
310 break;
311
312 case 39:
313 if (get_trans_state(operPtr.p) == TRANS_TOO_MUCH_AI) {
314 jam();
315 terrorCode = ZTOO_MUCH_ATTRINFO_ERROR;
316 } else if (get_trans_state(operPtr.p) == TRANS_ERROR_WAIT_TUPKEYREQ) {
317 jam();
318 terrorCode = ZSEIZE_ATTRINBUFREC_ERROR;
319 } else {
320 ndbrequire(false);
321 }//if
322 break;
323 case 40:
324 jam();
325 terrorCode = ZUNSUPPORTED_BRANCH;
326 break;
327 default:
328 ndbrequire(false);
329 break;
330 }//switch
331 tupkeyErrorLab(signal);
332 return -1;
333 }
334
early_tupkey_error(Signal * signal)335 void Dbtup::early_tupkey_error(Signal* signal)
336 {
337 Operationrec * const regOperPtr = operPtr.p;
338 ndbrequire(!regOperPtr->op_struct.in_active_list);
339 set_trans_state(regOperPtr, TRANS_IDLE);
340 set_tuple_state(regOperPtr, TUPLE_PREPARED);
341 initOpConnection(regOperPtr);
342 send_TUPKEYREF(signal, regOperPtr);
343 }
344
tupkeyErrorLab(Signal * signal)345 void Dbtup::tupkeyErrorLab(Signal* signal)
346 {
347 Operationrec * const regOperPtr = operPtr.p;
348 set_trans_state(regOperPtr, TRANS_IDLE);
349 set_tuple_state(regOperPtr, TUPLE_PREPARED);
350
351 FragrecordPtr fragPtr;
352 fragPtr.i= regOperPtr->fragmentPtr;
353 ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
354
355 TablerecPtr tabPtr;
356 tabPtr.i= fragPtr.p->fragTableId;
357 ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
358
359 if (regOperPtr->m_undo_buffer_space &&
360 (regOperPtr->is_first_operation() && regOperPtr->is_last_operation()))
361 {
362 c_lgman->free_log_space(fragPtr.p->m_logfile_group_id,
363 regOperPtr->m_undo_buffer_space);
364 }
365
366 Uint32 *ptr = 0;
367 if (!regOperPtr->m_tuple_location.isNull())
368 {
369 PagePtr tmp;
370 ptr= get_ptr(&tmp, ®OperPtr->m_tuple_location, tabPtr.p);
371 }
372
373
374 removeActiveOpList(regOperPtr, (Tuple_header*)ptr);
375 initOpConnection(regOperPtr);
376 send_TUPKEYREF(signal, regOperPtr);
377 }
378
send_TUPKEYREF(Signal * signal,Operationrec * const regOperPtr)379 void Dbtup::send_TUPKEYREF(Signal* signal,
380 Operationrec* const regOperPtr)
381 {
382 TupKeyRef * const tupKeyRef = (TupKeyRef *)signal->getDataPtrSend();
383 tupKeyRef->userRef = regOperPtr->userpointer;
384 tupKeyRef->errorCode = terrorCode;
385 sendSignal(DBLQH_REF, GSN_TUPKEYREF, signal,
386 TupKeyRef::SignalLength, JBB);
387 }
388
389 /**
390 * Unlink one operation from the m_operation_ptr_i list in the tuple.
391 */
removeActiveOpList(Operationrec * const regOperPtr,Tuple_header * tuple_ptr)392 void Dbtup::removeActiveOpList(Operationrec* const regOperPtr,
393 Tuple_header *tuple_ptr)
394 {
395 OperationrecPtr raoOperPtr;
396
397 if(!regOperPtr->m_copy_tuple_location.isNull())
398 {
399 jam();
400 c_undo_buffer.free_copy_tuple(®OperPtr->m_copy_tuple_location);
401 }
402
403 if (regOperPtr->op_struct.in_active_list) {
404 regOperPtr->op_struct.in_active_list= false;
405 if (regOperPtr->nextActiveOp != RNIL) {
406 jam();
407 raoOperPtr.i= regOperPtr->nextActiveOp;
408 c_operation_pool.getPtr(raoOperPtr);
409 raoOperPtr.p->prevActiveOp= regOperPtr->prevActiveOp;
410 } else {
411 jam();
412 tuple_ptr->m_operation_ptr_i = regOperPtr->prevActiveOp;
413 }
414 if (regOperPtr->prevActiveOp != RNIL) {
415 jam();
416 raoOperPtr.i= regOperPtr->prevActiveOp;
417 c_operation_pool.getPtr(raoOperPtr);
418 raoOperPtr.p->nextActiveOp= regOperPtr->nextActiveOp;
419 }
420 regOperPtr->prevActiveOp= RNIL;
421 regOperPtr->nextActiveOp= RNIL;
422 }
423 }
424