0001 Getting Started Tutorial
0002 ========================
0003 :doctype: book
0004
0005 == About the guide
0006
0007 Getting started tutorial covers Enduro/X installation from binary package,
0008 environment setup, creating a sample Enduro/X server and creating sample client.
0009 This include creating a necessary configuration files. Finally the application is booted,
0010 and client process calls the sample server process.
0011
0012 == Operating System configuration
0013
0014 Certain operating system configuration is required in order to Enduro/X running,
0015 see ex_adminman(guides)(Enduro/X Administration Manual, Setup System) section,
0016 the steps are crucial to be executed for chosen operating system before
0017 continuing.
0018
0019 == Installing binary package (RPM for Centos 6.x)
0020
0021 We will also need a gcc compiler to build our bankapp
0022 ---------------------------------------------------------------------
0023 # wget https://www.endurox.org/attachments/download/243/endurox-5.3.6-1.centos6_9_GNU.x86_64.rpm
0024 # rpm -i endurox-5.3.6-1.centos6_9_GNU.x86_64.rpm
0025 # yum install gcc
0026 ---------------------------------------------------------------------
0027
0028 == Configuring the application environment
0029
0030 We will run our app "app1" from new user "user1". Application domain will be
0031 located in /opt/app1 folder.
0032
0033 To create creating base environment, Enduro/X "provision" tool is used.
0034 This generates base layout of application. Additional folder will be created later.
0035
0036
0037 ---------------------------------------------------------------------
0038 # useradd -m user1
0039 # mkdir -p /opt/app1
0040 # chown user1 /opt/app1
0041 # su - user1
0042 $ cd /opt/app1
0043 $ xadmin provision -d \
0044 -v qprefix=app1 \
0045 -v installQ=n \
0046 -v eventSv=n \
0047 -v cpmSv=n \
0048 -v configSv=n \
0049 -v bridge=n \
0050 -v addubf=bank.fd
0051 ....
0052 Provision succeed!
0053 ---------------------------------------------------------------------
0054
0055 Above script uses defaults, and for some parameters values are specified:
0056
0057 .Parameters applied to provision script above
0058 [width="40%",options="header"]
0059 |=========================================================
0060 |Parameter|Value applied|Description
0061 |qprefix|app1|Application prefix
0062 |installQ|n|Do not configure persistent queue as not used in example
0063 |eventSv|n|Do not configure event server as not used in example
0064 |cpmSv|n|Do not configure client process monitor server as not used in example
0065 |configSv|n|Do not configure Common Configuration interface server as not used here
0066 |bridge|n|Do not install network bridge as not used in example
0067 |addubf|bank.fd|Additional Key-value field table/UBF field to be configured,
0068 used by sample later
0069 |=========================================================
0070
0071 After provision completed, add directories for source code
0072 ---------------------------------------------------------------------
0073 $ mkdir /opt/app1/test
0074 $ mkdir -p /opt/app1/src/bankcl
0075 $ mkdir -p /opt/app1/src/banksv
0076 ---------------------------------------------------------------------
0077
0078 Thus the final directory structure built for the application is
0079
0080 [options="compact"]
0081 - /opt/app1/conf - will contain configuration files.
0082 - /opt/app1/src/bankcl - Enduro/X sample client process source
0083 - /opt/app1/src/banksv - Enduro/X sample server process sources.
0084 - /opt/app1/bin - for executables.
0085 - /opt/app1/ubftab - for tables for field definitions.
0086 - /opt/app1/tmp - temp dir
0087 - /opt/app1/log - for logging
0088 - /opt/app1/test - test data
0089
0090
0091 For demo purposes the provision script have made more or less empty XATMI
0092 server configuration file found in */opt/app1/conf/ndrxconfig.xml*.
0093 Lets register firstly our XATMI server named *banksv* here first. Do this in
0094 *<servers/>* section add following *<server />* block in the file:
0095
0096 ---------------------------------------------------------------------
0097 <?xml version="1.0" ?>
0098 <endurox>
0099 ...
0100 </defaults>
0101 <servers>
0102 <server name="banksv">
0103 <srvid>1</srvid>
0104 <min>2</min>
0105 <max>2</max>
0106 <sysopt>-e /opt/app1/log/BANKSV -r</sysopt>
0107 </server>
0108 </servers>
0109 </endurox>
0110 ---------------------------------------------------------------------
0111
0112 Also we are about to add some logging settings for our binaries we are about
0113 to build, thus add following lines int the *[@debug]* section in application
0114 ini file (/opt/app1/conf/app.ini):
0115
0116 ---------------------------------------------------------------------
0117 [@debug]
0118 ..
0119 banksv= ndrx=5 ubf=0 tp=5 file=${NDRX_APPHOME}/log/BANKSV
0120 bankcl= ndrx=5 ubf=0 tp=5 file=${NDRX_APPHOME}/log/BANKCL
0121 ud= ndrx=5 ubf=0 file=${NDRX_APPHOME}/log/UD
0122 ---------------------------------------------------------------------
0123
0124 To learn more about debug configuration, see ndrxdebug.conf(5) manpage, note that
0125 document describes both formats legacy, where separate file was used and current
0126 one with Common-Configuration (i.e. using ini file section).
0127
0128
0129 If at this step we try to boot an application server, it should start fine,
0130 except that *banksv* binary won't be found:
0131
0132 ---------------------------------------------------------------------
0133 $ cd /opt/app1/conf
0134 $ source setapp1
0135 $ xadmin start -y
0136 Enduro/X 5.4.1, build Nov 7 2018 08:48:27, using SystemV for LINUX (64 bits)
0137
0138 Enduro/X Middleware Platform for Distributed Transaction Processing
0139 Copyright (C) 2009-2016 ATR Baltic Ltd.
0140 Copyright (C) 2017,2018 Mavimax Ltd. All Rights Reserved.
0141
0142 This software is released under one of the following licenses:
0143 AGPLv3 or Mavimax license for commercial use.
0144
0145 * Shared resources opened...
0146 * Enduro/X back-end (ndrxd) is not running
0147 * ndrxd PID (from PID file): 4716
0148 * ndrxd idle instance started.
0149 exec banksv -k 0myWI5nu -i 1 -e /opt/app1/log/BANKSV -r -- :
0150 process id=4720 ... Died.
0151 exec banksv -k 0myWI5nu -i 2 -e /opt/app1/log/BANKSV -r -- :
0152 process id=4723 ... Died.
0153 Startup finished. 0 processes started.
0154 ---------------------------------------------------------------------
0155
0156 This is ok, we have configured two copies of *banksv* Enduro/X servers,
0157 which we are not yet built, thus we get the error.
0158
0159 If you run `xadmin' and get following error:
0160
0161 ---------------------------------------------------------------------
0162 $ xadmin
0163 Failed to initialize!
0164 ---------------------------------------------------------------------
0165
0166 Then this typically means, that you do not have configure operating system properly
0167 see *Operating System configuration* section.
0168 More info is logged to /opt/app1/log/xadmin.log
0169
0170 == Creating the server process
0171
0172 Firstly to create a "bank" server, we will have to define the fields in
0173 which we will transfer the data. We will need following fields:
0174 [options="compact"]
0175 - T_ACCNUM - Account number, type string
0176 - T_ACCCUR - Account currency, type string
0177 - T_AMTAVL - Available balance in account, type double
0178
0179 So we will create a service "BALANCE" to which we will T_ACCNUM and T_ACCCUR.
0180 The process will return balance in T_AMTAVL.
0181
0182 === Defining the UBF fields
0183
0184 Required fields will be define into /opt/app1/ubftab/bank.fd with following contents:
0185
0186 ---------------------------------------------------------------------
0187 $/* -----------------------------------------------------------------------------
0188 $** Bank app field definitions for UBF buffer
0189 $** -----------------------------------------------------------------------------
0190 $*/
0191
0192 $#ifndef __BANK_H
0193 $#define __BANK_H
0194
0195 *base 1000
0196
0197 #NAME ID TYPE FLAG COMMENT
0198 #---- -- ---- ---- -------
0199 # Service name for UD
0200 T_ACCNUM 1 string - Account number
0201 T_ACCCUR 2 string - Account currency
0202 T_AMTAVL 3 double - Account balance
0203
0204 $#endif
0205 ---------------------------------------------------------------------
0206
0207 To generate C header fields for UBF buffer, run `mkfldhdr' command in
0208 /opt/app1/ubftab folder:
0209
0210 ---------------------------------------------------------------------
0211 $ mkfldhdr
0212 ...
0213 NDRX:5: 2038:000:20151116:033733008:fldhdr.c:0290:Finished with : SUCCESS
0214 $ ls -l
0215 total 16
0216 -rw-r--r--. 1 user1 user1 459 Nov 16 03:36 bank.fd
0217 -rw-rw-r--. 1 user1 user1 525 Nov 16 03:37 bank.fd.h
0218 -rw-r--r--. 1 user1 user1 3704 Nov 16 03:18 Exfields
0219 -rw-rw-r--. 1 user1 user1 3498 Nov 16 03:37 Exfields.h
0220 ---------------------------------------------------------------------
0221
0222 === Server source code
0223
0224 We will have sample server process which will just print in trace file account,
0225 currency. In return it will set "random" balance in field "T_AMTAVL".
0226 The source code of /opt/app1/src/banksv/banksv.c looks as follows:
0227
0228 ---------------------------------------------------------------------
0229 #include <stdio.h>
0230 #include <stdlib.h>
0231 #include <string.h>
0232 #include <time.h>
0233
0234 /* Enduro/X includes: */
0235 #include <atmi.h>
0236 #include <ubf.h>
0237 #include <bank.fd.h>
0238
0239 #define SUCCEED 0
0240 #define FAIL -1
0241
0242 /**
0243 * BALANCE service
0244 */
0245 void BALANCE (TPSVCINFO *p_svc)
0246 {
0247 int ret=SUCCEED;
0248 double balance;
0249 char account[28+1];
0250 char currency[3+1];
0251 BFLDLEN len;
0252
0253 UBFH *p_ub = (UBFH *)p_svc->data;
0254
0255 fprintf(stderr, "BALANCE got call\n");
0256
0257 /* Resize the buffer to have some space in... */
0258 if (NULL==(p_ub = (UBFH *)tprealloc ((char *)p_ub, 1024)))
0259 {
0260 fprintf(stderr, "Failed to realloc the UBF buffer - %s\n",
0261 tpstrerror(tperrno));
0262 ret=FAIL;
0263 goto out;
0264 }
0265
0266
0267 /* Read the account field */
0268 len = sizeof(account);
0269 if (SUCCEED!=Bget(p_ub, T_ACCNUM, 0, account, &len))
0270 {
0271 fprintf(stderr, "Failed to get T_ACCNUM[0]! - %s\n",
0272 Bstrerror(Berror));
0273 ret=FAIL;
0274 goto out;
0275 }
0276
0277 /* Read the currency field */
0278 len = sizeof(currency);
0279 if (SUCCEED!=Bget(p_ub, T_ACCCUR, 0, currency, &len))
0280 {
0281 fprintf(stderr, "Failed to get T_ACCCUR[0]! - %s\n",
0282 Bstrerror(Berror));
0283 ret=FAIL;
0284 goto out;
0285 }
0286
0287 fprintf(stderr, "Got request for account: [%s] currency [%s]\n",
0288 account, currency);
0289
0290 srand(time(NULL));
0291 balance = (double)rand()/(double)RAND_MAX + rand();
0292
0293 /* Return the value in T_AMTAVL field */
0294
0295 fprintf(stderr, "Retruning balance %lf\n", balance);
0296
0297
0298 if (SUCCEED!=Bchg(p_ub, T_AMTAVL, 0, (char *)&balance, 0L))
0299 {
0300 fprintf(stderr, "Failed to set T_AMTAVL! - %s\n",
0301 Bstrerror(Berror));
0302 ret=FAIL;
0303 goto out;
0304 }
0305
0306 out:
0307 tpreturn( ret==SUCCEED?TPSUCCESS:TPFAIL,
0308 0L,
0309 (char *)p_ub,
0310 0L,
0311 0L);
0312 }
0313
0314 /**
0315 * Do initialization
0316 */
0317 int tpsvrinit(int argc, char **argv)
0318 {
0319 if (SUCCEED!=tpadvertise("BALANCE", BALANCE))
0320 {
0321 fprintf(stderr, "Failed to advertise BALANCE - %s\n",
0322 tpstrerror(tperrno));
0323 return FAIL;
0324 }
0325
0326 return SUCCEED;
0327 }
0328
0329 /**
0330 * Do de-initialization
0331 */
0332 void tpsvrdone(void)
0333 {
0334 fprintf(stderr, "tpsvrdone called\n");
0335 }
0336 ---------------------------------------------------------------------
0337
0338 Very simple Makefile will look like (/opt/app1/src/banksv/Makefile):
0339
0340 ---------------------------------------------------------------------
0341 banksv: banksv.c
0342 cc -o banksv banksv.c -I. -I ../../ubftab -latmisrv -latmi -lubf -lnstd -lrt -ldl -lm
0343 ---------------------------------------------------------------------
0344
0345 Build the binary:
0346 ---------------------------------------------------------------------
0347 $ cd /opt/app1/src/banksv
0348 $ make
0349 cc -o banksv banksv.c -I. -I ../../ubftab -latmisrv -latmi -lubf -lnstd -lrt -ldl -lm
0350 ls -l
0351 total 20
0352 -rwxrwxr-x. 1 user1 user1 9937 Nov 16 04:11 banksv
0353 -rw-rw-r--. 1 user1 user1 1926 Nov 16 04:07 banksv.c
0354 -rw-rw-r--. 1 user1 user1 105 Nov 16 04:01 Makefile
0355 ---------------------------------------------------------------------
0356 So binary is built next we will try to start it.
0357
0358 === Booting the server process
0359
0360 To start the binary, first we need to copy it to binary directory:
0361 ---------------------------------------------------------------------
0362 $ cp /opt/app1/src/banksv/banksv /opt/app1/bin/banksv
0363 ---------------------------------------------------------------------
0364
0365 Now start it with "xadmin start". This will cause to boot any unbooted
0366 processes to start (which previosly did not start because we didn't have
0367 `banksv' executable in bin directory.
0368
0369 ---------------------------------------------------------------------
0370
0371 $ xadmin start -y
0372 Enduro/X 5.4.1, build Nov 12 2018 08:11:50, using SystemV for LINUX (64 bits)
0373
0374 Enduro/X Middleware Platform for Distributed Transaction Processing
0375 Copyright (C) 2009-2016 ATR Baltic Ltd.
0376 Copyright (C) 2017,2018 Mavimax Ltd. All Rights Reserved.
0377
0378 This software is released under one of the following licenses:
0379 AGPLv3 or Mavimax license for commercial use.
0380
0381 * Shared resources opened...
0382 * Enduro/X back-end (ndrxd) is not running
0383 * ndrxd PID (from PID file): 22128
0384 * ndrxd idle instance started.
0385 exec banksv -k 0myWI5nu -i 1 -e /opt/app1/log/BANKSV -r -- :
0386 process id=22132 ... Started.
0387 exec banksv -k 0myWI5nu -i 2 -e /opt/app1/log/BANKSV -r -- :
0388 process id=22136 ... Started.
0389 Startup finished. 2 processes started.
0390 ---------------------------------------------------------------------
0391
0392 To check that our BALANCE service is advertised, we can execute command
0393 "xadmin psc" - print services:
0394
0395 ---------------------------------------------------------------------
0396 $ xadmin psc
0397 Enduro/X 5.4.1, build Nov 12 2018 08:11:50, using SystemV for LINUX (64 bits)
0398
0399 Enduro/X Middleware Platform for Distributed Transaction Processing
0400 Copyright (C) 2009-2016 ATR Baltic Ltd.
0401 Copyright (C) 2017,2018 Mavimax Ltd. All Rights Reserved.
0402
0403 This software is released under one of the following licenses:
0404 AGPLv3 or Mavimax license for commercial use.
0405
0406 * Shared resources opened...
0407 * ndrxd PID (from PID file): 22128
0408 Nd Service Name Routine Name Prog Name SRVID #SUCC #FAIL MAX LAST STAT
0409 -- ------------ ------------ --------- ----- ----- ----- -------- -------- -----
0410 1 BALANCE BALANCE banksv 1 0 0 0ms 0ms AVAIL
0411 1 BALANCE BALANCE banksv 2 0 0 0ms 0ms AVAIL
0412 ---------------------------------------------------------------------
0413
0414 We see here two copies for *banksv* binaries running (Server ID 1 & 2).
0415 Both advertises "BALANCE" service.
0416
0417 === Testing the service with "ud" command
0418
0419 It is possible to call the service without a client process. This is useful
0420 for testing. Service can be called with `ud' utility. In which we define the
0421 target service name and any additional UBF buffer fields. In our case these
0422 fields are T_ACCNUM and T_ACCCUR, which are mandatory for the service. So we
0423 will create a `test.ud' file in folder /opt/app1/test. /opt/app1/test/test.ud
0424 looks like:
0425
0426 ---------------------------------------------------------------------
0427 SRVCNM BALANCE
0428 T_ACCNUM ABC123467890
0429 T_ACCCUR EUR
0430 ---------------------------------------------------------------------
0431
0432 To call the service just pipe the data to the `ud':
0433 ---------------------------------------------------------------------
0434 $ ud < /opt/app1/test/test.ud
0435 SENT pkt(1) is :
0436 T_ACCNUM ABC123467890
0437 T_ACCCUR EUR
0438
0439 RTN pkt(1) is :
0440 T_AMTAVL 1355808545.118969
0441 T_ACCNUM ABC123467890
0442 T_ACCCUR EUR
0443 ---------------------------------------------------------------------
0444 We see that our "dummy" balance returned is "1355808545.118969".
0445 So test service is working ok. Now we should write a client app, which could
0446 call the service via tpcall() XATMI API call.
0447
0448 == Creating the client application
0449 Bank client application will setup T_ACCNUM and T_ACCCUR fields and will
0450 call "BALANCE" service, after the call client application will
0451 print the balance on screen.
0452
0453 === Client binary source code
0454 Code for client application: /opt/app1/src/bankcl/bankcl.c
0455
0456 ---------------------------------------------------------------------
0457 #include <string.h>
0458 #include <stdio.h>
0459 #include <stdlib.h>
0460 #include <memory.h>
0461 #include <math.h>
0462
0463 #include <atmi.h>
0464 #include <ubf.h>
0465 #include <bank.fd.h>
0466
0467 #define SUCCEED 0
0468 #define FAIL -1
0469
0470 /**
0471 * Do the test call to the server
0472 */
0473 int main(int argc, char** argv) {
0474
0475 int ret=SUCCEED;
0476 UBFH *p_ub;
0477 long rsplen;
0478 double balance;
0479
0480 /* allocate the call buffer */
0481 if (NULL== (p_ub = (UBFH *)tpalloc("UBF", NULL, 1024)))
0482 {
0483 fprintf(stderr, "Failed to realloc the UBF buffer - %s\n",
0484 tpstrerror(tperrno));
0485 ret=FAIL;
0486 goto out;
0487 }
0488
0489 /* Set the data */
0490 if (SUCCEED!=Badd(p_ub, T_ACCNUM, "ACC00000000001", 0) ||
0491 SUCCEED!=Badd(p_ub, T_ACCCUR, "USD", 0))
0492 {
0493 fprintf(stderr, "Failed to get T_ACCNUM[0]! - %s\n",
0494 Bstrerror(Berror));
0495 ret=FAIL;
0496 goto out;
0497 }
0498
0499 /* Call the server */
0500 if (FAIL == tpcall("BALANCE", (char *)p_ub, 0L, (char **)&p_ub, &rsplen,0))
0501 {
0502 fprintf(stderr, "Failed to call BALANCE - %s\n",
0503 tpstrerror(tperrno));
0504
0505 ret=FAIL;
0506 goto out;
0507 }
0508
0509 /* Read the balance field */
0510
0511 if (SUCCEED!=Bget(p_ub, T_AMTAVL, 0, (char *)&balance, 0L))
0512 {
0513 fprintf(stderr, "Failed to get T_AMTAVL[0]! - %s\n",
0514 Bstrerror(Berror));
0515 ret=FAIL;
0516 goto out;
0517 }
0518
0519 printf("Account balance is: %.2lf USD\n", balance);
0520
0521 out:
0522 /* free the buffer */
0523 if (NULL!=p_ub)
0524 {
0525 tpfree((char *)p_ub);
0526 }
0527
0528 /* Terminate ATMI session */
0529 tpterm();
0530 return ret;
0531 }
0532 ---------------------------------------------------------------------
0533 Makefile (/opt/app1/src/bankcl/Makefile) looks like:
0534
0535 ---------------------------------------------------------------------
0536 bankcl: bankcl.c
0537 cc -o bankcl bankcl.c -I. -I ../../ubftab -latmiclt -latmi -lubf -lnstd -lrt -ldl -lm
0538 ---------------------------------------------------------------------
0539
0540 Once both bankcl.c and Makefile is created, you can run the build process:
0541 ---------------------------------------------------------------------
0542 $ cd /opt/app1/src/bankcl
0543 $ make
0544 $ ls -l
0545 total 20
0546 -rwxrwxr-x. 1 user1 user1 9471 Nov 22 13:34 bankcl
0547 -rw-rw-r--. 1 user1 user1 1380 Nov 22 13:34 bankcl.c
0548 -rw-rw-r--. 1 user1 user1 105 Nov 22 13:32 Makefile
0549 ---------------------------------------------------------------------
0550
0551 === Running the client process
0552 We will start the application from the same build directory. The results are following:
0553
0554 ---------------------------------------------------------------------
0555 $ /opt/app1/src/bankcl/bankcl
0556 Account balance is: 883078058.68 USD
0557 ---------------------------------------------------------------------
0558
0559 == Deploy "banksv" in Docker container
0560
0561 To deploy the example files in Docker container, follow the instructions found
0562 in endurox-docker repository: https://github.com/endurox-dev/endurox-docker
0563
0564
0565 == Conclusions
0566
0567 From the above sample it could be seen that creating a ATMI application is
0568 pretty easy and straight forward. This application was very basic,
0569 just doing the call to Enduro/X service. However the same application
0570 could work in cluster, where "BALANCE" service can be located on different
0571 physical machine and `bankcl' will still work, as platform will ensure the
0572 visibility of the "BALANCE" service, see the <<TPBRIDGE>> for clustering.
0573 The source files of the sample app are located in
0574 "getting_started_tutorial-files/opt/app1" folder.
0575
0576 :numbered!:
0577
0578 [bibliography]
0579 Additional documentation
0580 ------------------------
0581 This section lists additional related documents.
0582
0583 [bibliography]
0584 .Internet resources
0585 - [[[EX_ADMINGUIDE]]] ex_adminman(guides)
0586 - [[[MQ_OVERVIEW]]] 'man 7 mq_overview'
0587 - [[[EX_ENV]]] ex_env(5)
0588 - [[[NDRXCONFIG]]] ndrxconfig.xml(5)
0589 - [[[DEBUGCONF]]] ndrxdebug.conf(5)
0590 - [[[XADMIN]]] xadmin(8)
0591 - [[[TPBRIDGE]]] tpbridge(8)
0592
0593 [glossary]
0594 Glossary
0595 --------
0596 This section lists
0597
0598 [glossary]
0599 ATMI::
0600 Application Transaction Monitor Interface
0601
0602 UBF::
0603 Unified Buffer Format it is similar API as Tuxedo's FML
0604
0605
0606 ////////////////////////////////////////////////////////////////
0607 The index is normally left completely empty, it's contents being
0608 generated automatically by the DocBook toolchain.
0609 ////////////////////////////////////////////////////////////////