0001 /**
0002 * @brief Oracle PRO*C Sample database server
0003 *
0004 * @file atmisv47.proc
0005 */
0006 /* -----------------------------------------------------------------------------
0007 * Enduro/X Middleware Platform for Distributed Transaction Processing
0008 * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009 * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010 * This software is released under one of the following licenses:
0011 * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012 * See LICENSE file for full text.
0013 * -----------------------------------------------------------------------------
0014 * AGPL license:
0015 *
0016 * This program is free software; you can redistribute it and/or modify it under
0017 * the terms of the GNU Affero General Public License, version 3 as published
0018 * by the Free Software Foundation;
0019 *
0020 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022 * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023 * for more details.
0024 *
0025 * You should have received a copy of the GNU Affero General Public License along
0026 * with this program; if not, write to the Free Software Foundation, Inc.,
0027 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028 *
0029 * -----------------------------------------------------------------------------
0030 * A commercial use license is available from Mavimax, Ltd
0031 * contact@mavimax.com
0032 * -----------------------------------------------------------------------------
0033 */
0034
0035 #include <stdio.h>
0036 #include <stdlib.h>
0037
0038 #ifndef ORA_PROC
0039 #include <ndebug.h>
0040 #endif
0041
0042 #include <atmi.h>
0043 #include <ndrstandard.h>
0044 #include <ubf.h>
0045 #include <ubfutil.h>
0046 #include <test.fd.h>
0047 #include <string.h>
0048 #include "test47.h"
0049
0050 #include <sqlca.h>
0051
0052
0053 /*---------------------------Externs------------------------------------*/
0054 /*---------------------------Macros-------------------------------------*/
0055 #define PROC_RESTART do { \
0056 /* in dynamic mode Enduro/X xa libs may not track the point where\
0057 * SQL lost connection by it self\
0058 */\
0059 if (M_dyn && (-3135 == sqlca.sqlcode || -3114==sqlca.sqlcode))\
0060 {\
0061 NDRX_LOG(log_error, "Lost connection, let process to re-init");\
0062 if (tran_started)\
0063 {\
0064 tpabort(0);\
0065 }\
0066 tpexit();\
0067 }\
0068 } while(0)
0069
0070 /*---------------------------Enums--------------------------------------*/
0071 /*---------------------------Typedefs-----------------------------------*/
0072 /*---------------------------Globals------------------------------------*/
0073 /*---------------------------Statics------------------------------------*/
0074 exprivate char M_errmark[16] = "TESTERROR";
0075 exprivate long M_tout = 60;
0076 exprivate int M_dyn = EXFALSE; /* are we in dynamic mode? */
0077 /*---------------------------Prototypes---------------------------------*/
0078
0079 /**
0080 * Read "account" balance from DB
0081 * This will work with out transactions (as read only)
0082 */
0083 void BALANCE (TPSVCINFO *p_svc)
0084 {
0085 int ret=EXSUCCEED;
0086 UBFH *p_ub = (UBFH *)p_svc->data;
0087 int tran_started=EXFALSE;
0088
0089 EXEC SQL BEGIN DECLARE SECTION;
0090 long h_balance;
0091 char h_accnum[1024];
0092 EXEC SQL END DECLARE SECTION;
0093
0094 NDRX_LOG(log_debug, "%s got call", __func__);
0095
0096 if (!tpgetlev())
0097 {
0098 /* start a transaction */
0099 if (EXSUCCEED!=tpbegin(M_tout, 0))
0100 {
0101 NDRX_LOG(log_error, "Failed to start transaction: %s",
0102 tpstrerror(tperrno));
0103 EXFAIL_OUT(ret);
0104 }
0105 tran_started=EXTRUE;
0106 }
0107
0108 /* reallocate the buffer... */
0109 p_ub = (UBFH *)tprealloc((char *)p_ub, Bsizeof(p_ub) + 1024);
0110
0111 if (NULL==p_ub)
0112 {
0113 EXFAIL_OUT(ret);
0114 }
0115
0116 /* Just print the buffer */
0117 ndrx_debug_dump_UBF(log_debug, "BALANCE got call", p_ub);
0118
0119 if (EXFAIL==Bget(p_ub, T_STRING_FLD, 0, h_accnum, 0))
0120 {
0121 NDRX_LOG(log_error, "TESTERROR: Failed to get T_STRING_FLD: %s",
0122 Bstrerror(Berror));
0123 ret=EXFAIL;
0124 goto out;
0125 }
0126
0127 NDRX_LOG(log_info, "Search for account: %s", h_accnum);
0128
0129 EXEC SQL SELECT balance INTO :h_balance
0130 FROM accounts
0131 WHERE accnum = :h_accnum;
0132
0133 NDRX_LOG(log_info, "Result: %d", sqlca.sqlcode);
0134
0135 if (sqlca.sqlcode != 0)
0136 {
0137 NDRX_LOG(log_error, "Failed to select: %d: %.70s",
0138 sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
0139
0140 PROC_RESTART;
0141 EXFAIL_OUT(ret);
0142 }
0143
0144 if (EXFAIL==Bchg(p_ub, T_LONG_FLD, 0, (char *)&h_balance, 0))
0145 {
0146 NDRX_LOG(log_error, "TESTERROR: Failed to set h_balance: %s",
0147 Bstrerror(Berror));
0148 ret=EXFAIL;
0149 goto out;
0150 }
0151
0152 out:
0153
0154 if (tran_started)
0155 {
0156 if (EXSUCCEED==ret)
0157 {
0158 if (EXSUCCEED!=tpcommit(0))
0159 {
0160 NDRX_LOG(log_error, "Failed to commit: %s", tpstrerror(tperrno));
0161 ret=EXFAIL;
0162 }
0163 }
0164
0165 if (EXFAIL==ret)
0166 {
0167 if (EXSUCCEED!=tpabort(0))
0168 {
0169 NDRX_LOG(log_error, "Failed to abort: %s", tpstrerror(tperrno));
0170 }
0171 }
0172 }
0173
0174 tpreturn( ret==EXSUCCEED?TPSUCCESS:TPFAIL,
0175 0L,
0176 (char *)p_ub,
0177 0L,
0178 0L);
0179 }
0180
0181 /**
0182 * This service will make an account
0183 */
0184 void ACCOPEN (TPSVCINFO *p_svc)
0185 {
0186 int ret=EXSUCCEED;
0187 UBFH *p_ub = (UBFH *)p_svc->data;
0188 int tran_started=EXFALSE;
0189 EXEC SQL BEGIN DECLARE SECTION;
0190 long h_balance;
0191 char h_accnum[1024];
0192 EXEC SQL END DECLARE SECTION;
0193 TPTRANID trn;
0194
0195 NDRX_LOG(log_debug, "%s got call", __func__);
0196
0197 if (!tpgetlev())
0198 {
0199 /* start a transaction */
0200 if (EXSUCCEED!=tpbegin(M_tout, 0))
0201 {
0202 NDRX_LOG(log_error, "Failed to start transaction: %s",
0203 tpstrerror(tperrno));
0204 EXFAIL_OUT(ret);
0205 }
0206 tran_started=EXTRUE;
0207 }
0208
0209 /* Just print the buffer */
0210 ndrx_debug_dump_UBF(log_debug, "ACCOPEN got call", p_ub);
0211
0212
0213 if (EXSUCCEED!=tpsuspend (&trn, 0))
0214 {
0215 NDRX_LOG(log_error, "%s: failed to suspend: %s", M_errmark, tpstrerror(tperrno));
0216 EXFAIL_OUT(ret);
0217 }
0218
0219 if (EXSUCCEED!=tpresume (&trn, 0))
0220 {
0221 NDRX_LOG(log_error, "%s: failed to resume: %s", M_errmark, tpstrerror(tperrno));
0222 EXFAIL_OUT(ret);
0223 }
0224
0225 /* suspend again, now resume with no optimization */
0226 if (EXSUCCEED!=tpsuspend (&trn, 0))
0227 {
0228 NDRX_LOG(log_error, "%s: failed to suspend: %s", M_errmark, tpstrerror(tperrno));
0229 EXFAIL_OUT(ret);
0230 }
0231
0232 if (EXSUCCEED!=tpresume (&trn, TPTXNOOPTIM))
0233 {
0234 NDRX_LOG(log_error, "%s: failed to resume TPTXNOOPTIM: %s", M_errmark, tpstrerror(tperrno));
0235 EXFAIL_OUT(ret);
0236 }
0237
0238 /* OK continue... */
0239
0240 if (EXFAIL==Bget(p_ub, T_STRING_FLD, 0, h_accnum, 0))
0241 {
0242 NDRX_LOG(log_error, "TESTERROR: Failed to get T_STRING_FLD: %s",
0243 Bstrerror(Berror));
0244 ret=EXFAIL;
0245 goto out;
0246 }
0247
0248 if (EXFAIL==Bget(p_ub, T_LONG_FLD, 0, (char *)&h_balance, 0))
0249 {
0250 NDRX_LOG(log_error, "TESTERROR: Failed to get h_balance: %s",
0251 Bstrerror(Berror));
0252 ret=EXFAIL;
0253 goto out;
0254 }
0255
0256 NDRX_LOG(log_info, "Opening account: [%s] balance: [%ld]",
0257 h_accnum, h_balance);
0258
0259
0260 EXEC SQL INSERT INTO accounts(accnum, balance)
0261 VALUES(:h_accnum, :h_balance);
0262
0263 NDRX_LOG(log_info, "Result: %d", sqlca.sqlcode);
0264
0265 if (sqlca.sqlcode != 0)
0266 {
0267 NDRX_LOG(log_error, "Failed to select: %d: %.70s",
0268 sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
0269
0270 PROC_RESTART;
0271 EXFAIL_OUT(ret);
0272 }
0273
0274 out:
0275
0276 if (tran_started)
0277 {
0278 if (EXSUCCEED==ret)
0279 {
0280 if (EXSUCCEED!=tpcommit(0))
0281 {
0282 NDRX_LOG(log_error, "Failed to commit: %s", tpstrerror(tperrno));
0283 ret=EXFAIL;
0284 }
0285 }
0286
0287 if (EXFAIL==ret)
0288 {
0289 if (EXSUCCEED!=tpabort(0))
0290 {
0291 NDRX_LOG(log_error, "Failed to abort: %s", tpstrerror(tperrno));
0292 }
0293 }
0294 }
0295
0296 tpreturn( ret==EXSUCCEED?TPSUCCESS:TPFAIL,
0297 0L,
0298 (char *)p_ub,
0299 0L,
0300 0L);
0301 }
0302
0303
0304 /**
0305 * This service will make an account
0306 */
0307 void ACCCLEAN (TPSVCINFO *p_svc)
0308 {
0309 int ret=EXSUCCEED;
0310 int tran_started=EXFALSE;
0311 EXEC SQL BEGIN DECLARE SECTION;
0312 long h_balance;
0313 char h_accnum[1024];
0314 EXEC SQL END DECLARE SECTION;
0315
0316 NDRX_LOG(log_debug, "%s got call", __func__);
0317
0318 if (!tpgetlev())
0319 {
0320 /* start a transaction */
0321 if (EXSUCCEED!=tpbegin(M_tout, 0))
0322 {
0323 NDRX_LOG(log_error, "Failed to start transaction: %s",
0324 tpstrerror(tperrno));
0325 EXFAIL_OUT(ret);
0326 }
0327 tran_started=EXTRUE;
0328 }
0329
0330 EXEC SQL DELETE FROM ACCOUNTS;
0331
0332 NDRX_LOG(log_info, "Result: %d", sqlca.sqlcode);
0333
0334 if (sqlca.sqlcode != 0 && sqlca.sqlcode != 100)
0335 {
0336 NDRX_LOG(log_error, "Failed to delete: %d: %.70s",
0337 sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
0338
0339 PROC_RESTART;
0340 EXFAIL_OUT(ret);
0341 }
0342
0343 out:
0344
0345 if (tran_started)
0346 {
0347 if (EXSUCCEED==ret)
0348 {
0349 if (EXSUCCEED!=tpcommit(0))
0350 {
0351 NDRX_LOG(log_error, "Failed to commit: %s", tpstrerror(tperrno));
0352 ret=EXFAIL;
0353 }
0354 }
0355
0356 if (EXFAIL==ret)
0357 {
0358 if (EXSUCCEED!=tpabort(0))
0359 {
0360 NDRX_LOG(log_error, "Failed to abort: %s", tpstrerror(tperrno));
0361 }
0362 }
0363 }
0364
0365 tpreturn( ret==EXSUCCEED?TPSUCCESS:TPFAIL,
0366 0L,
0367 NULL,
0368 0L,
0369 0L);
0370 }
0371
0372 /**
0373 * Fetch testing
0374 */
0375 void FETCH (TPSVCINFO *p_svc)
0376 {
0377
0378 EXEC SQL BEGIN DECLARE SECTION;
0379 char h_typecode[17];
0380 EXEC SQL END DECLARE SECTION;
0381 int ret = EXSUCCEED;
0382 long rsplen = 0;
0383 char *odata;
0384
0385 EXEC SQL DECLARE type_cursor CURSOR FOR
0386 SELECT TYPECODE
0387 FROM ACCOUNT_TYPES;
0388
0389 if (sqlca.sqlcode != 0)
0390 {
0391 NDRX_LOG(log_error, "Failed to select: %d: %.70s",
0392 sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
0393 EXFAIL_OUT(ret);
0394 }
0395
0396 EXEC SQL OPEN type_cursor;
0397
0398 if (sqlca.sqlcode != 0)
0399 {
0400 NDRX_LOG(log_error, "Failed to select: %d: %.70s",
0401 sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
0402 EXFAIL_OUT(ret);
0403 }
0404
0405 for ( ;; )
0406 {
0407
0408 /* Fetching data */
0409 EXEC SQL FETCH type_cursor
0410 INTO :h_typecode;
0411
0412 if ( sqlca.sqlcode == 100 )
0413 {
0414 NDRX_LOG(log_debug, "EOF");
0415 goto out;
0416 }
0417
0418 if ( sqlca.sqlcode != 0 )
0419 {
0420 NDRX_LOG(log_error, "Failed to fetch: %d: %.70s",
0421 sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
0422 EXFAIL_OUT(ret);
0423 }
0424
0425 /* Perform service call (to have suspend) */
0426 odata=NULL;
0427 if (EXSUCCEED!=tpcall("DEL", NULL, 0, &odata, &rsplen, 0))
0428 {
0429 NDRX_LOG(log_error, "Failed to call DEL: %s", tpstrerror(tperrno));
0430 EXFAIL_OUT(ret);
0431 }
0432
0433 }
0434
0435 out:
0436 EXEC SQL CLOSE type_cursor;
0437
0438 tpreturn( ret==EXSUCCEED?TPSUCCESS:TPFAIL,
0439 0L,
0440 NULL,
0441 0L,
0442 0L);
0443
0444 }
0445
0446 /**
0447 * Do initialization
0448 */
0449 int NDRX_INTEGRA(tpsvrinit)(int argc, char **argv)
0450 {
0451 int ret = EXSUCCEED;
0452 char *p;
0453 NDRX_LOG(log_debug, "tpsvrinit called");
0454
0455 if (NULL!=getenv(KILL_TEST_ENV))
0456 {
0457 NDRX_STRCPY_SAFE(M_errmark, "LOOPERR");
0458 M_tout = MAX_RSP;
0459 }
0460
0461 if (NULL!=(p=getenv("NDRX_XA_DRIVERLIB")) && NULL!=strstr(p, "libndrxxaorad"))
0462 {
0463 M_dyn = EXTRUE;
0464 }
0465
0466 if (EXSUCCEED!=tpopen())
0467 {
0468 NDRX_LOG(log_error, "Failed to open DB!");
0469 EXFAIL_OUT(ret);
0470 }
0471
0472 if (EXSUCCEED!=tpadvertise("BALANCE", BALANCE))
0473 {
0474 NDRX_LOG(log_error, "Failed to initialize BALANCE!");
0475 EXFAIL_OUT(ret);
0476 }
0477
0478 if (EXSUCCEED!=tpadvertise("ACCOPEN", ACCOPEN))
0479 {
0480 NDRX_LOG(log_error, "Failed to initialize ACCOPEN!");
0481 EXFAIL_OUT(ret);
0482 }
0483
0484 if (EXSUCCEED!=tpadvertise("ACCCLEAN", ACCCLEAN))
0485 {
0486 NDRX_LOG(log_error, "Failed to initialize ACCCLEAN!");
0487 EXFAIL_OUT(ret);
0488 }
0489
0490 if (EXSUCCEED!=tpadvertise("FETCH", FETCH))
0491 {
0492 NDRX_LOG(log_error, "Failed to initialize FETCH!");
0493 EXFAIL_OUT(ret);
0494 }
0495
0496 out:
0497 return ret;
0498 }
0499
0500 /**
0501 * Do de-initialization
0502 */
0503 void NDRX_INTEGRA(tpsvrdone)(void)
0504 {
0505 NDRX_LOG(log_debug, "tpsvrdone called");
0506
0507 tpclose();
0508
0509 }
0510
0511 /* vim: set ts=4 sw=4 et smartindent: */