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 #include <string.h>
29 #include "userHandle.h"
30 #include "userInterface.h"
31 
32 #include "macros.h"
33 #include "ndb_schema.hpp"
34 #include "ndb_error.hpp"
35 
36 #include <NdbApi.hpp>
37 
38 
39 void
userCheckpoint(UserHandle * uh)40 userCheckpoint(UserHandle *uh){
41 }
42 
43 inline
44 NdbConnection *
startTransaction(Ndb * pNDB,ServerId inServerId,const SubscriberNumber inNumber)45 startTransaction(Ndb * pNDB, ServerId inServerId, const SubscriberNumber inNumber){
46 
47   const int keyDataLenBytes    = sizeof(ServerId)+SUBSCRIBER_NUMBER_LENGTH;
48   const int keyDataLen_64Words = keyDataLenBytes >> 3;
49 
50   Uint64 keyDataBuf[keyDataLen_64Words+1]; // The "+1" is for rounding...
51 
52   char     * keyDataBuf_charP = (char *)&keyDataBuf[0];
53   Uint32  * keyDataBuf_wo32P = (Uint32 *)&keyDataBuf[0];
54 
55   // Server Id comes first
56   keyDataBuf_wo32P[0] = inServerId;
57   // Then subscriber number
58   memcpy(&keyDataBuf_charP[sizeof(ServerId)], inNumber, SUBSCRIBER_NUMBER_LENGTH);
59 
60   return pNDB->startTransaction(0, keyDataBuf_charP, keyDataLenBytes);
61 }
62 
63 /**
64  * Transaction 1 - T1
65  *
66  * Update location and changed by/time on a subscriber
67  *
68  * Input:
69  *   SubscriberNumber,
70  *   Location,
71  *   ChangedBy,
72  *   ChangedTime
73  *
74  * Output:
75  */
76 void
userTransaction_T1(UserHandle * uh,SubscriberNumber number,Location new_location,ChangedBy changed_by,ChangedTime changed_time)77 userTransaction_T1(UserHandle * uh,
78 		   SubscriberNumber number,
79 		   Location new_location,
80 		   ChangedBy changed_by,
81 		   ChangedTime changed_time){
82   Ndb * pNDB = uh->pNDB;
83 
84   DEBUG2("T1(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
85 
86   int check;
87   NdbRecAttr * check2;
88 
89   NdbConnection * MyTransaction = pNDB->startTransaction();
90   if (MyTransaction != NULL) {
91     NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
92     if (MyOperation != NULL) {
93       MyOperation->updateTuple();
94       MyOperation->equal(IND_SUBSCRIBER_NUMBER,
95                          number);
96       MyOperation->setValue(IND_SUBSCRIBER_LOCATION,
97 		            (char *)&new_location);
98       MyOperation->setValue(IND_SUBSCRIBER_CHANGED_BY,
99 			    changed_by);
100       MyOperation->setValue(IND_SUBSCRIBER_CHANGED_TIME,
101 			    changed_time);
102       check = MyTransaction->execute( Commit );
103       if (check != -1) {
104         pNDB->closeTransaction(MyTransaction);
105         return;
106       } else {
107         CHECK_MINUS_ONE(check, "T1: Commit",
108 		        MyTransaction);
109       }//if
110     } else {
111       CHECK_NULL(MyOperation, "T1: getNdbOperation", MyTransaction);
112     }//if
113   } else {
114     error_handler("T1-1: startTranscation", pNDB->getNdbErrorString(), pNDB->getNdbError());
115   }//if
116 }
117 
118 /**
119  * Transaction 2 - T2
120  *
121  * Read from Subscriber:
122  *
123  * Input:
124  *   SubscriberNumber
125  *
126  * Output:
127  *   Location
128  *   Changed by
129  *   Changed Timestamp
130  *   Name
131  */
132 void
userTransaction_T2(UserHandle * uh,SubscriberNumber number,Location * readLocation,ChangedBy changed_by,ChangedTime changed_time,SubscriberName subscriberName)133 userTransaction_T2(UserHandle * uh,
134 		   SubscriberNumber number,
135 		   Location * readLocation,
136 		   ChangedBy changed_by,
137 		   ChangedTime changed_time,
138 		   SubscriberName subscriberName){
139   Ndb * pNDB = uh->pNDB;
140 
141   DEBUG2("T2(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
142 
143   int check;
144   NdbRecAttr * check2;
145 
146   NdbConnection * MyTransaction = pNDB->startTransaction();
147   if (MyTransaction == NULL)
148     error_handler("T2-1: startTransaction", pNDB->getNdbErrorString(), pNDB->getNdbError());
149 
150   NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
151   CHECK_NULL(MyOperation, "T2: getNdbOperation",
152 	     MyTransaction);
153 
154   MyOperation->readTuple();
155   MyOperation->equal(IND_SUBSCRIBER_NUMBER,
156 		     number);
157   MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
158 			(char *)readLocation);
159   MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
160 			changed_by);
161   MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
162                         changed_time);
163   MyOperation->getValue(IND_SUBSCRIBER_NAME,
164 			subscriberName);
165   check = MyTransaction->execute( Commit );
166   CHECK_MINUS_ONE(check, "T2: Commit",
167 		  MyTransaction);
168   pNDB->closeTransaction(MyTransaction);
169 }
170 
171 /**
172  * Transaction 3 - T3
173  *
174  * Read session details
175  *
176  * Input:
177  *   SubscriberNumber
178  *   ServerId
179  *   ServerBit
180  *
181  * Output:
182  *   BranchExecuted
183  *   SessionDetails
184  *   ChangedBy
185  *   ChangedTime
186  *   Location
187  */
188 void
userTransaction_T3(UserHandle * uh,SubscriberNumber inNumber,ServerId inServerId,ServerBit inServerBit,SessionDetails outSessionDetails,BranchExecuted * outBranchExecuted)189 userTransaction_T3(UserHandle * uh,
190 		   SubscriberNumber   inNumber,
191 		   ServerId           inServerId,
192 		   ServerBit          inServerBit,
193 		   SessionDetails     outSessionDetails,
194 		   BranchExecuted   * outBranchExecuted){
195   Ndb * pNDB = uh->pNDB;
196 
197   char               outChangedBy   [sizeof(ChangedBy)  +(4-(sizeof(ChangedBy)   & 3))];
198   char               outChangedTime [sizeof(ChangedTime)+(4-(sizeof(ChangedTime) & 3))];
199   Location           outLocation;
200   GroupId            groupId;
201   ActiveSessions     sessions;
202   Permission         permission;
203   SubscriberSuffix   inSuffix;
204 
205   DEBUG3("T3(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
206 
207   int check;
208   NdbRecAttr * check2;
209 
210   NdbConnection * MyTransaction = startTransaction(pNDB, inServerId, inNumber);
211   if (MyTransaction == NULL)
212     error_handler("T3-1: startTranscation", pNDB->getNdbErrorString(), pNDB->getNdbError());
213 
214   NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
215   CHECK_NULL(MyOperation, "T3-1: getNdbOperation",
216 	     MyTransaction);
217 
218   MyOperation->readTuple();
219   MyOperation->equal(IND_SUBSCRIBER_NUMBER,
220 			     inNumber);
221   MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
222 			(char *)&outLocation);
223   MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
224 			outChangedBy);
225   MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
226                         outChangedTime);
227   MyOperation->getValue(IND_SUBSCRIBER_GROUP,
228 			(char *)&groupId);
229   MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
230 			(char *)&sessions);
231   check = MyTransaction->execute( NoCommit );
232   CHECK_MINUS_ONE(check, "T3-1: NoCommit",
233 		  MyTransaction);
234 
235     /* Operation 2 */
236 
237   MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
238   CHECK_NULL(MyOperation, "T3-2: getNdbOperation",
239 	     MyTransaction);
240 
241 
242   MyOperation->readTuple();
243   MyOperation->equal(IND_GROUP_ID,
244 		     (char*)&groupId);
245   MyOperation->getValue(IND_GROUP_ALLOW_READ,
246 			(char *)&permission);
247   check = MyTransaction->execute( NoCommit );
248   CHECK_MINUS_ONE(check, "T3-2: NoCommit",
249 		  MyTransaction);
250 
251   if(((permission & inServerBit) == inServerBit) &&
252      ((sessions   & inServerBit) == inServerBit)){
253 
254     memcpy(inSuffix,
255 	   &inNumber[SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH], SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
256     DEBUG2("reading(%.*s) - ", SUBSCRIBER_NUMBER_SUFFIX_LENGTH, inSuffix);
257 
258     /* Operation 3 */
259     MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
260     CHECK_NULL(MyOperation, "T3-3: getNdbOperation",
261 	       MyTransaction);
262 
263     MyOperation->simpleRead();
264 
265     MyOperation->equal(IND_SESSION_SUBSCRIBER,
266 		       (char*)inNumber);
267     MyOperation->equal(IND_SESSION_SERVER,
268 		       (char*)&inServerId);
269     MyOperation->getValue(IND_SESSION_DATA,
270 			  (char *)outSessionDetails);
271     /* Operation 4 */
272     MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
273     CHECK_NULL(MyOperation, "T3-4: getNdbOperation",
274 	       MyTransaction);
275 
276     MyOperation->interpretedUpdateTuple();
277     MyOperation->equal(IND_SERVER_ID,
278 		       (char*)&inServerId);
279     MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
280 		        (char*)inSuffix);
281     MyOperation->incValue(IND_SERVER_READS, (uint32)1);
282     (* outBranchExecuted) = 1;
283   } else {
284     (* outBranchExecuted) = 0;
285   }
286   DEBUG("commit...");
287   check = MyTransaction->execute( Commit );
288   CHECK_MINUS_ONE(check, "T3: Commit",
289 		  MyTransaction);
290 
291   pNDB->closeTransaction(MyTransaction);
292 
293   DEBUG("done\n");
294 }
295 
296 
297 /**
298  * Transaction 4 - T4
299  *
300  * Create session
301  *
302  * Input:
303  *   SubscriberNumber
304  *   ServerId
305  *   ServerBit
306  *   SessionDetails,
307  *   DoRollback
308  * Output:
309  *   ChangedBy
310  *   ChangedTime
311  *   Location
312  *   BranchExecuted
313  */
314 void
userTransaction_T4(UserHandle * uh,SubscriberNumber inNumber,ServerId inServerId,ServerBit inServerBit,SessionDetails inSessionDetails,DoRollback inDoRollback,BranchExecuted * outBranchExecuted)315 userTransaction_T4(UserHandle * uh,
316 		   SubscriberNumber   inNumber,
317 		   ServerId           inServerId,
318 		   ServerBit          inServerBit,
319 		   SessionDetails     inSessionDetails,
320 		   DoRollback         inDoRollback,
321 		   BranchExecuted   * outBranchExecuted){
322 
323   Ndb * pNDB = uh->pNDB;
324 
325   char               outChangedBy   [sizeof(ChangedBy)  +(4-(sizeof(ChangedBy)   & 3))];
326   char               outChangedTime [sizeof(ChangedTime)+(4-(sizeof(ChangedTime) & 3))];
327   Location         outLocation;
328   GroupId          groupId;
329   ActiveSessions   sessions;
330   Permission       permission;
331   SubscriberSuffix inSuffix;
332 
333   DEBUG3("T4(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
334 
335   int check;
336   NdbRecAttr * check2;
337 
338   NdbConnection * MyTransaction = startTransaction(pNDB, inServerId, inNumber);
339   if (MyTransaction == NULL)
340     error_handler("T4-1: startTranscation", pNDB->getNdbErrorString(), pNDB->getNdbError());
341 
342   NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
343   CHECK_NULL(MyOperation, "T4-1: getNdbOperation",
344 	     MyTransaction);
345 
346   MyOperation->interpretedUpdateTuple();
347   MyOperation->equal(IND_SUBSCRIBER_NUMBER,
348 		     inNumber);
349   MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
350 			(char *)&outLocation);
351   MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
352 		        outChangedBy);
353   MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
354                         outChangedTime);
355   MyOperation->getValue(IND_SUBSCRIBER_GROUP,
356 			(char *)&groupId);
357   MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
358 			(char *)&sessions);
359   MyOperation->incValue(IND_SUBSCRIBER_SESSIONS,
360 			(uint32)inServerBit);
361   check = MyTransaction->execute( NoCommit );
362 
363     /* Operation 2 */
364 
365   MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
366   CHECK_NULL(MyOperation, "T4-2: getNdbOperation",
367 	     MyTransaction);
368 
369   MyOperation->readTuple();
370   MyOperation->equal(IND_GROUP_ID,
371 		     (char*)&groupId);
372   MyOperation->getValue(IND_GROUP_ALLOW_INSERT,
373 			(char *)&permission);
374   check = MyTransaction->execute( NoCommit );
375   CHECK_MINUS_ONE(check, "T4-2: NoCommit",
376 		  MyTransaction);
377 
378   if(((permission & inServerBit) == inServerBit) &&
379      ((sessions   & inServerBit) == 0)){
380 
381     memcpy(inSuffix,
382 	   &inNumber[SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH], SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
383 
384     DEBUG2("inserting(%.*s) - ", SUBSCRIBER_NUMBER_SUFFIX_LENGTH, inSuffix);
385 
386     /* Operation 3 */
387 
388     MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
389     CHECK_NULL(MyOperation, "T4-3: getNdbOperation",
390 	       MyTransaction);
391 
392     MyOperation->insertTuple();
393     MyOperation->equal(IND_SESSION_SUBSCRIBER,
394 		      (char*)inNumber);
395     MyOperation->equal(IND_SESSION_SERVER,
396 		       (char*)&inServerId);
397     MyOperation->setValue(SESSION_DATA,
398 			  (char *)inSessionDetails);
399     /* Operation 4 */
400 
401     /* Operation 5 */
402     MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
403     CHECK_NULL(MyOperation, "T4-5: getNdbOperation",
404 	       MyTransaction);
405 
406     MyOperation->interpretedUpdateTuple();
407     MyOperation->equal(IND_SERVER_ID,
408 		       (char*)&inServerId);
409     MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
410 		       (char*)inSuffix);
411     MyOperation->incValue(IND_SERVER_INSERTS, (uint32)1);
412     (* outBranchExecuted) = 1;
413   } else {
414     (* outBranchExecuted) = 0;
415     DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
416     DEBUG1("%s", ((sessions   & inServerBit) ? "in session - " : "no in session - "));
417   }
418 
419   if(!inDoRollback && (* outBranchExecuted)){
420     DEBUG("commit\n");
421     check = MyTransaction->execute( Commit );
422     CHECK_MINUS_ONE(check, "T4: Commit",
423 		    MyTransaction);
424   } else {
425     DEBUG("rollback\n");
426     check = MyTransaction->execute(Rollback);
427     CHECK_MINUS_ONE(check, "T4:Rollback",
428 		    MyTransaction);
429 
430   }
431 
432   pNDB->closeTransaction(MyTransaction);
433 }
434 
435 
436 /**
437  * Transaction 5 - T5
438  *
439  * Delete session
440  *
441  * Input:
442  *   SubscriberNumber
443  *   ServerId
444  *   ServerBit
445  *   DoRollback
446  * Output:
447  *   ChangedBy
448  *   ChangedTime
449  *   Location
450  *   BranchExecuted
451  */
452 void
userTransaction_T5(UserHandle * uh,SubscriberNumber inNumber,ServerId inServerId,ServerBit inServerBit,DoRollback inDoRollback,BranchExecuted * outBranchExecuted)453 userTransaction_T5(UserHandle * uh,
454 		   SubscriberNumber   inNumber,
455 		   ServerId           inServerId,
456 		   ServerBit          inServerBit,
457 		   DoRollback         inDoRollback,
458 		   BranchExecuted   * outBranchExecuted){
459   Ndb * pNDB = uh->pNDB;
460 
461   DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
462 
463   NdbConnection * MyTransaction = 0;
464   NdbOperation  * MyOperation = 0;
465 
466   char             outChangedBy   [sizeof(ChangedBy)  +(4-(sizeof(ChangedBy)   & 3))];
467   char             outChangedTime [sizeof(ChangedTime)+(4-(sizeof(ChangedTime) & 3))];
468   Location         outLocation;
469   GroupId          groupId;
470   ActiveSessions   sessions;
471   Permission       permission;
472   SubscriberSuffix inSuffix;
473 
474   int check;
475   NdbRecAttr * check2;
476 
477   MyTransaction = pNDB->startTransaction();
478   if (MyTransaction == NULL)
479     error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), pNDB->getNdbError());
480 
481   MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
482   CHECK_NULL(MyOperation, "T5-1: getNdbOperation",
483 	     MyTransaction);
484 
485   MyOperation->interpretedUpdateTuple();
486   MyOperation->equal(IND_SUBSCRIBER_NUMBER,
487 		     inNumber);
488   MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
489 		        (char *)&outLocation);
490   MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
491 			&outChangedBy[0]);
492   MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
493                         &outChangedTime[0]);
494   MyOperation->getValue(IND_SUBSCRIBER_GROUP,
495 		        (char *)&groupId);
496   MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
497 		        (char *)&sessions);
498   MyOperation->subValue(IND_SUBSCRIBER_SESSIONS,
499 		        (uint32)inServerBit);
500   MyTransaction->execute( NoCommit );
501     /* Operation 2 */
502 
503   MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
504   CHECK_NULL(MyOperation, "T5-2: getNdbOperation",
505 	     MyTransaction);
506 
507   MyOperation->readTuple();
508   MyOperation->equal(IND_GROUP_ID,
509 		     (char*)&groupId);
510   MyOperation->getValue(IND_GROUP_ALLOW_DELETE,
511 			(char *)&permission);
512   check = MyTransaction->execute( NoCommit );
513   CHECK_MINUS_ONE(check, "T5-2: NoCommit",
514 		  MyTransaction);
515 
516   if(((permission & inServerBit) == inServerBit) &&
517      ((sessions   & inServerBit) == inServerBit)){
518 
519     memcpy(inSuffix,
520 	   &inNumber[SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH], SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
521 
522     DEBUG2("deleting(%.*s) - ", SUBSCRIBER_NUMBER_SUFFIX_LENGTH, inSuffix);
523 
524     /* Operation 3 */
525     MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
526     CHECK_NULL(MyOperation, "T5-3: getNdbOperation",
527 	       MyTransaction);
528 
529     MyOperation->deleteTuple();
530     MyOperation->equal(IND_SESSION_SUBSCRIBER,
531 		       (char*)inNumber);
532     MyOperation->equal(IND_SESSION_SERVER,
533 		       (char*)&inServerId);
534     /* Operation 4 */
535 
536     /* Operation 5 */
537     MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
538     CHECK_NULL(MyOperation, "T5-5: getNdbOperation",
539 	       MyTransaction);
540 
541 
542     MyOperation->interpretedUpdateTuple();
543     MyOperation->equal(IND_SERVER_ID,
544 		       (char*)&inServerId);
545     MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
546 		       (char*)inSuffix);
547     MyOperation->incValue(IND_SERVER_DELETES, (uint32)1);
548     (* outBranchExecuted) = 1;
549   } else {
550     (* outBranchExecuted) = 0;
551     DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
552     DEBUG1("%s", ((sessions   & inServerBit) ? "in session - " : "no in session - "));
553   }
554 
555   if(!inDoRollback && (* outBranchExecuted)){
556     DEBUG("commit\n");
557     check = MyTransaction->execute( Commit );
558     CHECK_MINUS_ONE(check, "T5: Commit",
559 		    MyTransaction);
560   } else {
561     DEBUG("rollback\n");
562     check = MyTransaction->execute(Rollback);
563     CHECK_MINUS_ONE(check, "T5:Rollback",
564 		    MyTransaction);
565 
566   }
567 
568   pNDB->closeTransaction(MyTransaction);
569 }
570 
571