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, &regOperPtr.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(&regOperPtr.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, &regOperPtr->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(&regOperPtr->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