Back to home page

Enduro/X

 
 

    


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 ////////////////////////////////////////////////////////////////