1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3     All rights reserved. Use is subject to license terms.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License, version 2.0,
7    as published by the Free Software Foundation.
8 
9    This program is also distributed with certain software (including
10    but not limited to OpenSSL) that is licensed under separate terms,
11    as designated in a particular file or component or in included license
12    documentation.  The authors of MySQL hereby grant you an additional
13    permission to link the program and your derivative works with the
14    separately licensed software that they have included with MySQL.
15 
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License, version 2.0, for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 */
25 
26 //#define DEBUG_ON
27 
28 extern "C" {
29 #include "user_transaction.h"
30 };
31 
32 #include "macros.h"
33 #include "ndb_schema.hpp"
34 #include "ndb_error.hpp"
35 
36 #include <time.h>
37 #include <NdbApi.hpp>
38 
39 /**
40  * Transaction 1 - T1
41  *
42  * Update location and changed by/time on a subscriber
43  *
44  * Input:
45  *   SubscriberNumber,
46  *   Location,
47  *   ChangedBy,
48  *   ChangedTime
49  *
50  * Output:
51  */
52 int
T1(void * obj,const SubscriberNumber number,const Location new_location,const ChangedBy changed_by,const ChangedTime changed_time,BenchmarkTime * transaction_time)53 T1(void * obj,
54    const SubscriberNumber number,
55    const Location new_location,
56    const ChangedBy changed_by,
57    const ChangedTime changed_time,
58    BenchmarkTime * transaction_time){
59 
60   Ndb * pNDB = (Ndb *) obj;
61 
62   DEBUG2("T1(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
63 
64   BenchmarkTime start;
65   get_time(&start);
66 
67   int check;
68   NdbRecAttr * check2;
69 
70   NdbConnection * MyTransaction = pNDB->startTransaction();
71   if (MyTransaction == NULL)
72     error_handler("T1-1: startTranscation", pNDB->getNdbErrorString(), 0);
73 
74   NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
75   CHECK_NULL(MyOperation, "T1: getNdbOperation", MyTransaction);
76 
77   check = MyOperation->updateTuple();
78   CHECK_MINUS_ONE(check, "T1: updateTuple",
79 		  MyTransaction);
80 
81   check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
82 			     number);
83   CHECK_MINUS_ONE(check, "T1: equal subscriber",
84 		  MyTransaction);
85 
86   check = MyOperation->setValue(IND_SUBSCRIBER_LOCATION,
87 				(char *)&new_location);
88   CHECK_MINUS_ONE(check, "T1: setValue location",
89 		  MyTransaction);
90 
91   check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_BY,
92 				changed_by);
93   CHECK_MINUS_ONE(check, "T1: setValue changed_by",
94 		  MyTransaction);
95 
96   check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_TIME,
97 				changed_time);
98   CHECK_MINUS_ONE(check, "T1: setValue changed_time",
99 		  MyTransaction);
100 
101   check = MyTransaction->execute( Commit );
102   CHECK_MINUS_ONE(check, "T1: Commit",
103 		  MyTransaction);
104 
105   pNDB->closeTransaction(MyTransaction);
106 
107   get_time(transaction_time);
108   time_diff(transaction_time, &start);
109   return 0;
110 }
111 
112 /**
113  * Transaction 2 - T2
114  *
115  * Read from Subscriber:
116  *
117  * Input:
118  *   SubscriberNumber
119  *
120  * Output:
121  *   Location
122  *   Changed by
123  *   Changed Timestamp
124  *   Name
125  */
126 int
T2(void * obj,const SubscriberNumber number,Location * readLocation,ChangedBy changed_by,ChangedTime changed_time,SubscriberName subscriberName,BenchmarkTime * transaction_time)127 T2(void * obj,
128    const SubscriberNumber number,
129    Location * readLocation,
130    ChangedBy changed_by,
131    ChangedTime changed_time,
132    SubscriberName subscriberName,
133    BenchmarkTime * transaction_time){
134 
135   Ndb * pNDB = (Ndb *) obj;
136 
137   DEBUG2("T2(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
138 
139   BenchmarkTime start;
140   get_time(&start);
141 
142   int check;
143   NdbRecAttr * check2;
144 
145   NdbConnection * MyTransaction = pNDB->startTransaction();
146   if (MyTransaction == NULL)
147     error_handler("T2-1: startTranscation", pNDB->getNdbErrorString(), 0);
148 
149   NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
150   CHECK_NULL(MyOperation, "T2: getNdbOperation",
151 	     MyTransaction);
152 
153 
154   check = MyOperation->readTuple();
155   CHECK_MINUS_ONE(check, "T2: readTuple",
156 		  MyTransaction);
157 
158   check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
159 			     number);
160   CHECK_MINUS_ONE(check, "T2: equal subscriber",
161 		  MyTransaction);
162 
163   check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
164 				(char *)readLocation);
165   CHECK_NULL(check2, "T2: getValue location",
166 	     MyTransaction);
167 
168   check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
169 				 changed_by);
170   CHECK_NULL(check2, "T2: getValue changed_by",
171 	     MyTransaction);
172 
173   check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
174                                  changed_time);
175   CHECK_NULL(check2, "T2: getValue changed_time",
176 	     MyTransaction);
177 
178   check2 = MyOperation->getValue(IND_SUBSCRIBER_NAME,
179 				subscriberName);
180   CHECK_NULL(check2, "T2: getValue name",
181 	     MyTransaction);
182 
183   check = MyTransaction->execute( Commit );
184   CHECK_MINUS_ONE(check, "T2: Commit",
185 		  MyTransaction);
186 
187   pNDB->closeTransaction(MyTransaction);
188 
189   get_time(transaction_time);
190   time_diff(transaction_time, &start);
191   return 0;
192 }
193 
194 /**
195  * Transaction 3 - T3
196  *
197  * Read session details
198  *
199  * Input:
200  *   SubscriberNumber
201  *   ServerId
202  *   ServerBit
203  *
204  * Output:
205  *   BranchExecuted
206  *   SessionDetails
207  *   ChangedBy
208  *   ChangedTime
209  *   Location
210  */
211 int
T3(void * obj,const SubscriberNumber inNumber,const SubscriberSuffix inSuffix,const ServerId inServerId,const ServerBit inServerBit,SessionDetails outSessionDetails,ChangedBy outChangedBy,ChangedTime outChangedTime,Location * outLocation,BranchExecuted * outBranchExecuted,BenchmarkTime * outTransactionTime)212 T3(void * obj,
213    const SubscriberNumber   inNumber,
214    const SubscriberSuffix   inSuffix,
215    const ServerId           inServerId,
216    const ServerBit          inServerBit,
217    SessionDetails     outSessionDetails,
218    ChangedBy          outChangedBy,
219    ChangedTime        outChangedTime,
220    Location         * outLocation,
221    BranchExecuted   * outBranchExecuted,
222    BenchmarkTime    * outTransactionTime){
223 
224   Ndb * pNDB = (Ndb *) obj;
225 
226   GroupId        groupId;
227   ActiveSessions sessions;
228   Permission     permission;
229 
230   BenchmarkTime start;
231   get_time(&start);
232 
233   int check;
234   NdbRecAttr * check2;
235 
236   NdbConnection * MyTransaction = pNDB->startTransaction();
237   if (MyTransaction == NULL)
238     error_handler("T3-1: startTranscation", pNDB->getNdbErrorString(), 0);
239 
240   NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
241   CHECK_NULL(MyOperation, "T3-1: getNdbOperation",
242 	     MyTransaction);
243 
244   check = MyOperation->readTuple();
245   CHECK_MINUS_ONE(check, "T3-1: readTuple",
246 		  MyTransaction);
247 
248   check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
249 			     inNumber);
250   CHECK_MINUS_ONE(check, "T3-1: equal subscriber",
251 		  MyTransaction);
252 
253   check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
254 				 (char *)outLocation);
255   CHECK_NULL(check2, "T3-1: getValue location",
256 	     MyTransaction);
257 
258   check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
259 				 outChangedBy);
260   CHECK_NULL(check2, "T3-1: getValue changed_by",
261 	     MyTransaction);
262 
263   check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
264                                  outChangedTime);
265   CHECK_NULL(check2, "T3-1: getValue changed_time",
266 	     MyTransaction);
267 
268   check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
269 				 (char *)&groupId);
270   CHECK_NULL(check2, "T3-1: getValue group",
271 	     MyTransaction);
272 
273   check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
274 				 (char *)&sessions);
275   CHECK_NULL(check2, "T3-1: getValue sessions",
276 	     MyTransaction);
277 
278   check = MyTransaction->execute( NoCommit );
279   CHECK_MINUS_ONE(check, "T3-1: NoCommit",
280 		  MyTransaction);
281 
282     /* Operation 2 */
283 
284   MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
285   CHECK_NULL(MyOperation, "T3-2: getNdbOperation",
286 	     MyTransaction);
287 
288 
289   check = MyOperation->readTuple();
290   CHECK_MINUS_ONE(check, "T3-2: readTuple",
291 		  MyTransaction);
292 
293   check = MyOperation->equal(IND_GROUP_ID,
294 		     (char*)&groupId);
295   CHECK_MINUS_ONE(check, "T3-2: equal group",
296 		  MyTransaction);
297 
298   check2 = MyOperation->getValue(IND_GROUP_ALLOW_READ,
299 				 (char *)&permission);
300   CHECK_NULL(check2, "T3-2: getValue allow_read",
301 	     MyTransaction);
302 
303   check = MyTransaction->execute( NoCommit );
304   CHECK_MINUS_ONE(check, "T3-2: NoCommit",
305 		  MyTransaction);
306 
307   DEBUG3("T3(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
308 
309   if(((permission & inServerBit) == inServerBit) &&
310      ((sessions   & inServerBit) == inServerBit)){
311 
312     DEBUG("reading - ");
313 
314     /* Operation 3 */
315     MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
316     CHECK_NULL(MyOperation, "T3-3: getNdbOperation",
317 	       MyTransaction);
318 
319     check = MyOperation->simpleRead();
320     CHECK_MINUS_ONE(check, "T3-3: readTuple",
321 		    MyTransaction);
322 
323     check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
324 			       (char*)inNumber);
325     CHECK_MINUS_ONE(check, "T3-3: equal number",
326 		    MyTransaction);
327 
328     check = MyOperation->equal(IND_SESSION_SERVER,
329 			       (char*)&inServerId);
330     CHECK_MINUS_ONE(check, "T3-3: equal server id",
331 		    MyTransaction);
332 
333     check2 = MyOperation->getValue(IND_SESSION_DATA,
334 				   (char *)outSessionDetails);
335     CHECK_NULL(check2, "T3-3: getValue session details",
336 	       MyTransaction);
337 
338     /* Operation 4 */
339     MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
340     CHECK_NULL(MyOperation, "T3-4: getNdbOperation",
341 	       MyTransaction);
342 
343     check = MyOperation->interpretedUpdateTuple();
344     CHECK_MINUS_ONE(check, "T3-4: interpretedUpdateTuple",
345 		    MyTransaction);
346 
347     check = MyOperation->equal(IND_SERVER_ID,
348 			       (char*)&inServerId);
349     CHECK_MINUS_ONE(check, "T3-4: equal serverId",
350 		    MyTransaction);
351 
352     check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
353 			       (char*)inSuffix);
354     CHECK_MINUS_ONE(check, "T3-4: equal suffix",
355 		    MyTransaction);
356 
357     check = MyOperation->incValue(IND_SERVER_READS, (uint32)1);
358     CHECK_MINUS_ONE(check, "T3-4: inc value",
359 		    MyTransaction);
360     (* outBranchExecuted) = 1;
361   } else {
362     (* outBranchExecuted) = 0;
363   }
364   DEBUG("commit...");
365   check = MyTransaction->execute( Commit );
366   CHECK_MINUS_ONE(check, "T3: Commit",
367 		  MyTransaction);
368 
369   pNDB->closeTransaction(MyTransaction);
370 
371   DEBUG("done\n");
372   get_time(outTransactionTime);
373   time_diff(outTransactionTime, &start);
374   return 0;
375 }
376 
377 
378 /**
379  * Transaction 4 - T4
380  *
381  * Create session
382  *
383  * Input:
384  *   SubscriberNumber
385  *   ServerId
386  *   ServerBit
387  *   SessionDetails,
388  *   DoRollback
389  * Output:
390  *   ChangedBy
391  *   ChangedTime
392  *   Location
393  *   BranchExecuted
394  */
395 int
T4(void * obj,const SubscriberNumber inNumber,const SubscriberSuffix inSuffix,const ServerId inServerId,const ServerBit inServerBit,const SessionDetails inSessionDetails,ChangedBy outChangedBy,ChangedTime outChangedTime,Location * outLocation,DoRollback inDoRollback,BranchExecuted * outBranchExecuted,BenchmarkTime * outTransactionTime)396 T4(void * obj,
397    const SubscriberNumber   inNumber,
398    const SubscriberSuffix   inSuffix,
399    const ServerId           inServerId,
400    const ServerBit          inServerBit,
401    const SessionDetails     inSessionDetails,
402    ChangedBy          outChangedBy,
403    ChangedTime        outChangedTime,
404    Location         * outLocation,
405    DoRollback         inDoRollback,
406    BranchExecuted   * outBranchExecuted,
407    BenchmarkTime    * outTransactionTime){
408 
409   Ndb * pNDB = (Ndb *) obj;
410 
411   GroupId        groupId;
412   ActiveSessions sessions;
413   Permission     permission;
414 
415   BenchmarkTime start;
416   get_time(&start);
417 
418   int check;
419   NdbRecAttr * check2;
420 
421   NdbConnection * MyTransaction = pNDB->startTransaction();
422   if (MyTransaction == NULL)
423     error_handler("T4-1: startTranscation", pNDB->getNdbErrorString(), 0);
424 
425   NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
426   CHECK_NULL(MyOperation, "T4-1: getNdbOperation",
427 	     MyTransaction);
428 
429   check = MyOperation->interpretedUpdateTuple();
430   CHECK_MINUS_ONE(check, "T4-1: readTuple",
431 		  MyTransaction);
432 
433   check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
434 			     inNumber);
435   CHECK_MINUS_ONE(check, "T4-1: equal subscriber",
436 		  MyTransaction);
437 
438   check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
439 				 (char *)outLocation);
440   CHECK_NULL(check2, "T4-1: getValue location",
441 	     MyTransaction);
442 
443   check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
444 				 outChangedBy);
445   CHECK_NULL(check2, "T4-1: getValue changed_by",
446 	     MyTransaction);
447 
448   check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
449                                  outChangedTime);
450   CHECK_NULL(check2, "T4-1: getValue changed_time",
451 	     MyTransaction);
452 
453   check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
454 				 (char *)&groupId);
455   CHECK_NULL(check2, "T4-1: getValue group",
456 	     MyTransaction);
457 
458   check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
459 				 (char *)&sessions);
460   CHECK_NULL(check2, "T4-1: getValue sessions",
461 	     MyTransaction);
462 
463   check = MyOperation->incValue(IND_SUBSCRIBER_SESSIONS,
464 				(uint32)inServerBit);
465   CHECK_MINUS_ONE(check, "T4-4: inc value",
466 		  MyTransaction);
467 
468   check = MyTransaction->execute( NoCommit );
469   CHECK_MINUS_ONE(check, "T4-1: NoCommit",
470 		  MyTransaction);
471 
472     /* Operation 2 */
473 
474   MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
475   CHECK_NULL(MyOperation, "T4-2: getNdbOperation",
476 	     MyTransaction);
477 
478   check = MyOperation->readTuple();
479   CHECK_MINUS_ONE(check, "T4-2: readTuple",
480 		  MyTransaction);
481 
482   check = MyOperation->equal(IND_GROUP_ID,
483 		     (char*)&groupId);
484   CHECK_MINUS_ONE(check, "T4-2: equal group",
485 		  MyTransaction);
486 
487   check2 = MyOperation->getValue(IND_GROUP_ALLOW_INSERT,
488 				 (char *)&permission);
489   CHECK_NULL(check2, "T4-2: getValue allow_insert",
490 	     MyTransaction);
491 
492   check = MyTransaction->execute( NoCommit );
493   CHECK_MINUS_ONE(check, "T4-2: NoCommit",
494 		  MyTransaction);
495 
496   DEBUG3("T4(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
497 
498   if(((permission & inServerBit) == inServerBit) &&
499      ((sessions   & inServerBit) == 0)){
500 
501     DEBUG("inserting - ");
502 
503     /* Operation 3 */
504 
505     MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
506     CHECK_NULL(MyOperation, "T4-3: getNdbOperation",
507 	       MyTransaction);
508 
509     check = MyOperation->insertTuple();
510     CHECK_MINUS_ONE(check, "T4-3: insertTuple",
511 		    MyTransaction);
512 
513     check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
514 			       (char*)inNumber);
515     CHECK_MINUS_ONE(check, "T4-3: equal number",
516 		    MyTransaction);
517 
518     check = MyOperation->equal(IND_SESSION_SERVER,
519 			       (char*)&inServerId);
520     CHECK_MINUS_ONE(check, "T4-3: equal server id",
521 		    MyTransaction);
522 
523     check = MyOperation->setValue(SESSION_DATA,
524 				   (char *)inSessionDetails);
525     CHECK_MINUS_ONE(check, "T4-3: setValue session details",
526 	       MyTransaction);
527 
528     /* Operation 4 */
529 
530     /* Operation 5 */
531     MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
532     CHECK_NULL(MyOperation, "T4-5: getNdbOperation",
533 	       MyTransaction);
534 
535     check = MyOperation->interpretedUpdateTuple();
536     CHECK_MINUS_ONE(check, "T4-5: interpretedUpdateTuple",
537 		    MyTransaction);
538 
539     check = MyOperation->equal(IND_SERVER_ID,
540 			       (char*)&inServerId);
541     CHECK_MINUS_ONE(check, "T4-5: equal serverId",
542 		    MyTransaction);
543 
544     check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
545 			       (char*)inSuffix);
546     CHECK_MINUS_ONE(check, "T4-5: equal suffix",
547 		    MyTransaction);
548 
549     check = MyOperation->incValue(IND_SERVER_INSERTS, (uint32)1);
550     CHECK_MINUS_ONE(check, "T4-5: inc value",
551 		    MyTransaction);
552 
553     (* outBranchExecuted) = 1;
554   } else {
555     DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
556     DEBUG1("%s", ((sessions   & inServerBit) ? "in session - " : "no in session - "));
557     (* outBranchExecuted) = 0;
558   }
559 
560   if(!inDoRollback && (* outBranchExecuted)){
561     DEBUG("commit\n");
562     check = MyTransaction->execute( Commit );
563     CHECK_MINUS_ONE(check, "T4: Commit",
564 		    MyTransaction);
565   } else {
566     DEBUG("rollback\n");
567     check = MyTransaction->execute(Rollback);
568     CHECK_MINUS_ONE(check, "T4:Rollback",
569 		    MyTransaction);
570 
571   }
572 
573   pNDB->closeTransaction(MyTransaction);
574 
575   get_time(outTransactionTime);
576   time_diff(outTransactionTime, &start);
577   return 0;
578 }
579 
580 
581 /**
582  * Transaction 5 - T5
583  *
584  * Delete session
585  *
586  * Input:
587  *   SubscriberNumber
588  *   ServerId
589  *   ServerBit
590  *   DoRollback
591  * Output:
592  *   ChangedBy
593  *   ChangedTime
594  *   Location
595  *   BranchExecuted
596  */
597 int
T5(void * obj,const SubscriberNumber inNumber,const SubscriberSuffix inSuffix,const ServerId inServerId,const ServerBit inServerBit,ChangedBy outChangedBy,ChangedTime outChangedTime,Location * outLocation,DoRollback inDoRollback,BranchExecuted * outBranchExecuted,BenchmarkTime * outTransactionTime)598 T5(void * obj,
599    const SubscriberNumber   inNumber,
600    const SubscriberSuffix   inSuffix,
601    const ServerId           inServerId,
602    const ServerBit          inServerBit,
603    ChangedBy          outChangedBy,
604    ChangedTime        outChangedTime,
605    Location         * outLocation,
606    DoRollback         inDoRollback,
607    BranchExecuted   * outBranchExecuted,
608    BenchmarkTime    * outTransactionTime){
609 
610   Ndb           * pNDB = (Ndb *) obj;
611   NdbConnection * MyTransaction = 0;
612   NdbOperation  * MyOperation = 0;
613 
614   GroupId        groupId;
615   ActiveSessions sessions;
616   Permission     permission;
617 
618   BenchmarkTime start;
619   get_time(&start);
620 
621   int check;
622   NdbRecAttr * check2;
623 
624   MyTransaction = pNDB->startTransaction();
625   if (MyTransaction == NULL)
626     error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), 0);
627 
628   MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
629   CHECK_NULL(MyOperation, "T5-1: getNdbOperation",
630 	     MyTransaction);
631 
632   check = MyOperation->interpretedUpdateTuple();
633   CHECK_MINUS_ONE(check, "T5-1: readTuple",
634 		  MyTransaction);
635 
636   check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
637 			     inNumber);
638   CHECK_MINUS_ONE(check, "T5-1: equal subscriber",
639 		  MyTransaction);
640 
641   check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
642 				 (char *)outLocation);
643   CHECK_NULL(check2, "T5-1: getValue location",
644 	     MyTransaction);
645 
646   check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
647 				 outChangedBy);
648   CHECK_NULL(check2, "T5-1: getValue changed_by",
649 	     MyTransaction);
650 
651   check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
652                                  outChangedTime);
653   CHECK_NULL(check2, "T5-1: getValue changed_time",
654 	     MyTransaction);
655 
656   check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
657 				 (char *)&groupId);
658   CHECK_NULL(check2, "T5-1: getValue group",
659 	     MyTransaction);
660 
661   check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
662 				 (char *)&sessions);
663   CHECK_NULL(check2, "T5-1: getValue sessions",
664 	     MyTransaction);
665 
666   check = MyOperation->subValue(IND_SUBSCRIBER_SESSIONS,
667 				(uint32)inServerBit);
668   CHECK_MINUS_ONE(check, "T5-4: dec value",
669 		  MyTransaction);
670 
671   check = MyTransaction->execute( NoCommit );
672   CHECK_MINUS_ONE(check, "T5-1: NoCommit",
673 		  MyTransaction);
674 
675     /* Operation 2 */
676 
677   MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
678   CHECK_NULL(MyOperation, "T5-2: getNdbOperation",
679 	     MyTransaction);
680 
681 
682   check = MyOperation->readTuple();
683   CHECK_MINUS_ONE(check, "T5-2: readTuple",
684 		  MyTransaction);
685 
686   check = MyOperation->equal(IND_GROUP_ID,
687 		     (char*)&groupId);
688   CHECK_MINUS_ONE(check, "T5-2: equal group",
689 		  MyTransaction);
690 
691   check2 = MyOperation->getValue(IND_GROUP_ALLOW_DELETE,
692 				 (char *)&permission);
693   CHECK_NULL(check2, "T5-2: getValue allow_delete",
694 	     MyTransaction);
695 
696   check = MyTransaction->execute( NoCommit );
697   CHECK_MINUS_ONE(check, "T5-2: NoCommit",
698 		  MyTransaction);
699 
700   DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
701 
702   if(((permission & inServerBit) == inServerBit) &&
703      ((sessions   & inServerBit) == inServerBit)){
704 
705     DEBUG("deleting - ");
706 
707     /* Operation 3 */
708     MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
709     CHECK_NULL(MyOperation, "T5-3: getNdbOperation",
710 	       MyTransaction);
711 
712     check = MyOperation->deleteTuple();
713     CHECK_MINUS_ONE(check, "T5-3: deleteTuple",
714 		    MyTransaction);
715 
716     check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
717 			       (char*)inNumber);
718     CHECK_MINUS_ONE(check, "T5-3: equal number",
719 		    MyTransaction);
720 
721     check = MyOperation->equal(IND_SESSION_SERVER,
722 			       (char*)&inServerId);
723     CHECK_MINUS_ONE(check, "T5-3: equal server id",
724 		    MyTransaction);
725 
726     /* Operation 4 */
727 
728     /* Operation 5 */
729     MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
730     CHECK_NULL(MyOperation, "T5-5: getNdbOperation",
731 	       MyTransaction);
732 
733 
734     check = MyOperation->interpretedUpdateTuple();
735     CHECK_MINUS_ONE(check, "T5-5: interpretedUpdateTuple",
736 		    MyTransaction);
737 
738     check = MyOperation->equal(IND_SERVER_ID,
739 			       (char*)&inServerId);
740     CHECK_MINUS_ONE(check, "T5-5: equal serverId",
741 		    MyTransaction);
742 
743     check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
744 			       (char*)inSuffix);
745     CHECK_MINUS_ONE(check, "T5-5: equal suffix",
746 		    MyTransaction);
747 
748     check = MyOperation->incValue(IND_SERVER_DELETES, (uint32)1);
749     CHECK_MINUS_ONE(check, "T5-5: inc value",
750 		    MyTransaction);
751 
752     (* outBranchExecuted) = 1;
753   } else {
754     DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
755     DEBUG1("%s", ((sessions   & inServerBit) ? "in session - " : "no in session - "));
756     (* outBranchExecuted) = 0;
757   }
758 
759   if(!inDoRollback && (* outBranchExecuted)){
760     DEBUG("commit\n");
761     check = MyTransaction->execute( Commit );
762     CHECK_MINUS_ONE(check, "T5: Commit",
763 		    MyTransaction);
764   } else {
765     DEBUG("rollback\n");
766     check = MyTransaction->execute(Rollback);
767     CHECK_MINUS_ONE(check, "T5:Rollback",
768 		    MyTransaction);
769 
770   }
771 
772   pNDB->closeTransaction(MyTransaction);
773 
774   get_time(outTransactionTime);
775   time_diff(outTransactionTime, &start);
776   return 0;
777 }
778 
779