Back to home page

Enduro/X

 
 

    


0001 Enduro/X Internal/External Developer Guide
0002 ==========================================
0003 :doctype: book
0004 
0005 == Enduro/X Development standard
0006 
0007 Enduro/X build system is CMake. Version used should be 2.8 and above. It uses
0008 Flex and Bison for building UBF (FML) Expressions.
0009 
0010 Enduro/X is programmed in NetBeans C/C++ project. NetBeans supports CMake projects.
0011 Some command line editing usually is done by using VIM editor. The source code is
0012 appended with mode line settings. Thus to get the proper indention enabled, configure
0013 VIM editor before doing any edits append ~/.vimrc with following commands:
0014 
0015 --------------------------------------------------------------------------------
0016 set nocompatible 
0017 filetype plugin on
0018 set modeline 
0019 --------------------------------------------------------------------------------
0020 
0021 Project also uses 'libxml2' (provided by system), 'exhash' (already included 
0022 in 'include' dir) and cgreen (integrated into Enduro/X) for unit testing.
0023 
0024 === C Programming style
0025 
0026 This chapter points out key aspects of doing code changes in Enduro/X C core.
0027 
0028 ==== Indentation
0029 
0030 For code formatting Enduro/X C code uses Allman Indentation style, e.g.
0031 
0032 --------------------------------------------------------------------------------
0033 
0034 void something(void)
0035 {
0036     ...
0037 }
0038 
0039 while (x == y)
0040 {
0041     something();
0042     somethingelse();
0043 }
0044 
0045 finalthing();
0046 
0047 --------------------------------------------------------------------------------
0048 
0049 with indention of 4 spaces.
0050 
0051 
0052 ==== Variable compare with constants
0053 
0054 In case if in C compare variable with constants, the constant must be first
0055 and the follow the variable. This allows to escape from the errors when accidentally
0056 by writing single *=* assignment is made instead of compare, which might lead
0057 to unpredictable errors.
0058 
0059 For example
0060 
0061 --------------------------------------------------------------------------------
0062 
0063 #define SOME_CONST 10
0064 int i=5;
0065 
0066 /* THIS IS BAD STYLE */
0067 if (i==SOME_CONST)
0068 {
0069     ...
0070 }
0071 
0072 /* THIS IS GOOD STYLE */
0073 if (SOME_CONST==i)
0074 {
0075     ...
0076 }
0077 
0078 --------------------------------------------------------------------------------
0079 
0080 
0081 ==== Error handling
0082 
0083 All API calls which Enduro/X uses, must be error checked. When error is detected,
0084 it must be logged with corresponding logger. Either 'ndrx' or 'ubf' logger. 'ubf'
0085 logger (UBF_LOG() macros) shall be used only for libubf library. All other libraries
0086 shall log with NDRX_LOG() macros.
0087 
0088 The critical errors which are more like system error or some very wrong configuration
0089 shall be logged with *userlog()* too. This ensures that during the production
0090 operations, administrators can see the 
0091 
0092 Enduro/X uses "goto" as escape from function in case of error. The all functions
0093 that shall handle the errors (i.e. and not return any other error identifier like
0094 NULL pointer), the function shall bring with it self an 'ret' (return state) variable
0095 the simple integer. The 'ret' by default shall be set to 'EXSUCCEED' from ndrstandard.h
0096 header. The exit of function shall be marked with "out" label. After the out some
0097 de-init and status printing could be done. When error occurs, recommended way
0098 to escape is to write some log about the situation and use macro EXFAIL_OUT(ret),
0099 which effectively set the 'ret' to EXFAIL and performs 'goto out;'.
0100 
0101 
0102 Some examples of error handling:
0103 
0104 -------------------------------------------------------------------------------- 
0105 
0106 #include <ndrstandard.h>
0107 
0108 ...
0109 
0110 /**
0111  * Some error function
0112  * @param some_arg cannot be less than 0
0113  * @return EXFAIL (on failure), EXSUCCEED (all OK)
0114  */
0115 expublic int ndrx_some_func(int some_arg)
0116 {
0117     int ret = EXSUCCEED;
0118 
0119     if (some_arg < 0)
0120     {
0121         /* what is ret=EXFAIL; goto out; */
0122         EXFAIL_OUT(ret);
0123     }
0124 
0125 
0126 out:
0127 
0128     return ret;    
0129 }
0130 
0131 
0132 --------------------------------------------------------------------------------
0133 
0134 ==== Code with
0135 
0136 The code line length should be more or less 80 symbols. If function arguments
0137 are going wider, then moved some to next line. If string goes over the 80 chars
0138 then string shall be spitted with standard compiler concatenation done by C.
0139 
0140 
0141 Typical word wrap should look like:
0142 
0143 --------------------------------------------------------------------------------
0144 
0145     /* lock call descriptor */
0146     if (!(flags & TPNOREPLY))
0147     {
0148         /* get the call descriptor */
0149         if (EXFAIL==(tpcall_cd = get_call_descriptor_and_lock(&call->callseq, 
0150                 timestamp, flags)))
0151         {
0152             NDRX_LOG(log_error, "Do not have resources for "
0153                                 "track this call!");
0154             ndrx_TPset_error_fmt(TPELIMIT, "%s:All call descriptor entries have been used "
0155                                 "(check why they do not free up? Maybe need to "
0156                                 "use tpcancel()?)", __func__);
0157             EXFAIL_OUT(ret);
0158         }
0159     }
0160     else
0161     {
0162         NDRX_LOG(log_warn, "TPNOREPLY => cd=0");
0163         tpcall_cd = 0;
0164     }
0165 
0166 --------------------------------------------------------------------------------
0167 
0168 ==== Function visibility
0169 
0170 Function visibility in C is controlled by *static* prefix for functions. If
0171 one is present, then function visibility is at object file level, if prefix
0172 is not present, then function visibility is global exported symbol. To make
0173 it more clear, Enduro/X SDK includes two macros
0174 
0175 . expublic - empty macros to indicate that function names is available globally.
0176 
0177 . exprivate - substitute for *static* keyword. Function visibility is at file
0178 level.
0179 
0180 
0181 for example:
0182 
0183 --------------------------------------------------------------------------------
0184 
0185 #include <ndrstandard.h>
0186 
0187 expublic void ndrx_some_global_func(void)
0188 {
0189     return;
0190 }
0191 
0192 exprivate void some_local_func(void)
0193 {
0194     return;
0195 }
0196 
0197 --------------------------------------------------------------------------------
0198 
0199 ==== Code documentation
0200 
0201 *ALL* written code must be properly commented, so that other source maintainers
0202 can clearly understand what's going on at particular case. Comments are welcome.
0203 
0204 Regarding the mandatory documentation, Enduro/X uses Doxygen / JavaDoc style
0205 comments for functions, macros and files, so that the API documentation can
0206 be generated by doxygen. All function arguments must be documented at any level.
0207 
0208 
0209 File beginning must start with following block:
0210 
0211 --------------------------------------------------------------------------------
0212 
0213 /**
0214  * @brief Short description of the file purpose 
0215  *
0216  * @file file.name
0217  */
0218 >>> License block <<<
0219 --------------------------------------------------------------------------------
0220 
0221 The structure for C code is denoted by following comments (see bellow). This
0222 also include the sample type definitions and comments for given resources.
0223 Where possible grouping of comments shall be made. So that it could be denoted
0224 to user commons of the resources.
0225 
0226 --------------------------------------------------------------------------------
0227 
0228 
0229 /*---------------------------Includes-----------------------------------*/
0230 #include <ndrstandard.h> /* Enduro/X standard header */
0231 /*---------------------------Externs------------------------------------*/
0232 /** This is global variable */
0233 extern int ndrx_G_some_global; /** < this is other way to document... */
0234 /*---------------------------Macros-------------------------------------*/
0235 #define HELLO /**< This is hello world macros */
0236 
0237 
0238 /**
0239  * This is group of worlds (this is detailed description of group)
0240  * @defgroup worldsgrp Group of worlds (short description of group)
0241  * @{
0242  */
0243 
0244 #define WORLD_1 /**< Hello world 1 */
0245 #define WORLD_2 /**< Hello world 2 */
0246 /** Hello world 3 define, use this if the comment line is too large to fit
0247  * together in 80 symbols
0248  */
0249 #define WORLD_3
0250 /** @} */ /* end of worldsgrp */
0251 
0252 /*---------------------------Enums--------------------------------------*/
0253 /*---------------------------Typedefs-----------------------------------*/
0254 
0255 /**
0256  * Some structure used for ...
0257  */
0258 struct some_struct
0259 {
0260     int some_field; /**< some field descr */
0261 };
0262 
0263 /**
0264  * This is type of \ref some_struct used for ...
0265  * thus we reference the structure here.
0266  */
0267 typedef struct some_struct some_struct_t;
0268 
0269 /*---------------------------Globals------------------------------------*/
0270 /*---------------------------Statics------------------------------------*/
0271 /*---------------------------Prototypes---------------------------------*/
0272 
0273 --------------------------------------------------------------------------------
0274 
0275 Where each of the section shall included the given type of resources declared.
0276 
0277 Function documentation is following, by example:
0278 
0279 --------------------------------------------------------------------------------
0280 
0281 /**
0282  * This is example of some function. This is description of func.
0283  * @param[in] arg1 this is input argument
0284  * @param[in,out] arg2 this is output argument
0285  * @return in case of success function returns ptr to updated \p arg2 
0286  *   in case of error NULL is returned.
0287  */
0288 expublic char *ndrx_some_func(int arg1, char *arg2)
0289 {
0290     return NULL;
0291 }
0292 
0293 --------------------------------------------------------------------------------
0294 
0295 === Writing Enduro/X manuals
0296 
0297 Following asciidoc rules applies to certain document parts:
0298 
0299 *Bold applies to (in asciidoc asterisks)* to things that user is expected to write verbatim, for example:
0300 
0301 - References to other man pages (e.g. *ndrxd(8)*).
0302 
0303 - Binary names (e.g. *ndrxd(8)*).
0304 
0305 - Environment variable names  (e.g. *NDRX_NORMWAITMAX*).
0306 
0307 - Configuration section names (e.g. *[@xadmin/<$NDRX_CCTAG>]*).
0308 
0309 - Resource file names (e.g. */etc/xadmin.config*).
0310 
0311 - Constants, UBF field names (e.g. *EX_NETOURIP*).
0312 
0313 - Command line arguments.
0314 
0315 - Configuration parameter names.
0316 
0317 'Underline applies to (in asciidoc single quotes)' applies to things that user
0318 is expected to fill in:
0319 
0320 - File names.
0321 
0322 - parameter value labels.
0323 
0324 - Variables and field names in the structure.
0325 
0326 === Reserved identifier prefixes
0327 
0328 As the C language do not have prefixes like for high level languages (Java, C#, etc),
0329 for C developers have to prefix their identifier so that there is no conflict between
0330 different party code blocks. This is the case for Enduro/X too. Enduro/X have
0331 reserved following keywords as a prefixes for identifiers:
0332 
0333 . NDRX - system wide internal Enduro/X identifiers
0334 
0335 . ndrx - system wide internal Enduro/X identifiers
0336 
0337 . EX - system wide internal Enduro/X identifiers
0338 
0339 . ex - system wide internal Enduro/X identifiers
0340 
0341 . tp - used for user functions for ATMI protocol
0342 
0343 . B - used for UBF buffer API
0344 
0345 . atmi - internal identifiers for tp functions
0346 
0347 . edb - LMDB renamed for Enduro/X internal usage
0348 
0349 === Global variable naming policy
0350 
0351 Global variables (non static exported from the object file) shall be named with
0352 following scheme: 
0353 
0354 . 'ndrx_G_<variable name>'. 
0355 
0356 The old naming scheme included only 'G' in the front, but we are moving the the
0357 common naming scheme with 'NDRX'/'ndrx' in the front of the all exported
0358 identifiers.
0359 
0360 
0361 === Reserved UBF field numbers
0362 
0363 Enduro/X have reserved some list of typed UBF buffer field identifiers for internal use.
0364 The list is following:
0365 
0366 . 1-3999
0367 
0368 . 6000-10000
0369 
0370 . 30000001-33554431
0371 
0372 For user following field IDs are available:
0373 
0374 . 4000-5999
0375 
0376 . 10001-30000000
0377 
0378 Unit testing
0379 ------------
0380 
0381 Bot UBF and ATMI sub-systems are unit tested. UBF tests are located under 
0382 'ubftest' folder, which could be run by:
0383 
0384 --------------------------------------------------------------------------------
0385 $ ./ubfunit1 2>/dev/null
0386 Running "main"...
0387 Completed "main": 5749 passes, 0 failures, 0 exceptions.
0388 --------------------------------------------------------------------------------
0389 
0390 ATMI tests are located at 'atmitest' directory, can be run by:
0391 --------------------------------------------------------------------------------
0392 $ ./run.sh 
0393 tail -n1 test.out
0394 Completed "main": 18 passes, 0 failure, 0 exceptions.
0395 --------------------------------------------------------------------------------
0396 
0397 == Source code indexing with glimpse
0398 So that developers would be more simple to orient in the source code from command
0399 line, Enduro/X build system offers use of glimpse tool to index the source code.
0400 
0401 
0402 === Glimpse installation
0403 
0404 On Ubuntu like GNU/Linux systems, glimpse can be installed in following way:
0405 
0406 
0407 --------------------------------------------------------------------------------
0408 
0409 $ sudo apt install glimpse
0410 
0411 --------------------------------------------------------------------------------
0412 
0413 On other systems where glimpse does not come out of the box, it can be compiled
0414 from source code, download here: http://webglimpse.net/download.php
0415 
0416 For example:
0417 
0418 --------------------------------------------------------------------------------
0419 $ wget http://webglimpse.net/trial/glimpse-latest.tar.gz
0420 $ tar -xzf glimpse-latest.tar.gz
0421 $ cd glimpse-4.18.6
0422 $ ./configure
0423 $ make 
0424 $ sudo make install
0425 --------------------------------------------------------------------------------
0426 
0427 Glimpse requires (when compiled from sources) Flex shared library, on Ubuntu
0428 this can be installed by:
0429 
0430 --------------------------------------------------------------------------------
0431 
0432 $ sudo apt-get install libfl-dev
0433 
0434 --------------------------------------------------------------------------------
0435 
0436 === Source indexing and searching
0437 
0438 Once Enduro/X project is checked out, built and Glimpse is installed, you may
0439 index the source code using following make target:
0440 
0441 --------------------------------------------------------------------------------
0442 
0443 $ make index
0444 
0445 This is glimpseindex version 4.18.7, 2015.
0446 
0447 Indexing "/home/user1/projects/endurox" ...
0448 
0449 Size of files being indexed = 9941954 B, Total #of files = 1664
0450 
0451 Index-directory: "/home/user1/projects/endurox/glimpse_index"
0452 Glimpse-files created here:
0453 -rw-rw-r-- 1 user1 user1    171 Aug 18 07:30 .glimpse_exclude
0454 -rw------- 1 user1 user1 123657 Aug 18 08:59 .glimpse_filenames
0455 -rw------- 1 user1 user1   6656 Aug 18 08:59 .glimpse_filenames_index
0456 -rw------- 1 user1 user1      0 Aug 18 08:59 .glimpse_filetimes
0457 -rw------- 1 user1 user1 451169 Aug 18 08:59 .glimpse_index
0458 -rw------- 1 user1 user1    306 Aug 18 08:59 .glimpse_messages
0459 -rw------- 1 user1 user1    836 Aug 18 08:59 .glimpse_partitions
0460 -rw------- 1 user1 user1 380242 Aug 18 08:59 .glimpse_statistics
0461 Built target index
0462 
0463 --------------------------------------------------------------------------------
0464 
0465 This also generates search command script at project root. So for example, now
0466 to search for tpcall, we can use following command from project root (or 
0467 any other folder, because "/home/user1/projects/endurox/glim" includes full
0468 path to project).
0469 
0470 --------------------------------------------------------------------------------
0471 
0472 $ ./glim tpcall
0473 Your query may search about 33% of the total space! Continue? (y/n)y
0474 /home/user1/projects/endurox/tpevsrv/tpevsv.c:                 if (EXFAIL==(tpcallex (tmpsvc, p_svc->data, p_svc->len,  
0475 /home/user1/projects/endurox/tpevsrv/tpevsv.c:  * Event name carried in extradata of tpcallex()
0476 /home/user1/projects/endurox/libnetproto/proto.c: #define TTC        7 /* tpcall */
0477 /home/user1/projects/endurox/libatmisrv/tpreturn.c:  *                  or tpcall wrapper)
0478 ...
0479 
0480 --------------------------------------------------------------------------------
0481 
0482 In case if some files or directories must be excluded from the index path (
0483 used at make index phase), the editing can be done in glimpse_index/.glimpse_exclude
0484 file at project root directory.
0485 
0486 
0487 == Enduro/X libraries
0488 
0489 The framework is composed by following internal libraries and it's dependencies:
0490 [dia, module_dependency.dia, module_dependency.png, x300]
0491 -------------------------------
0492 -------------------------------
0493 
0494 Common configuration
0495 --------------------
0496 
0497 Enduro/X users are welcome to use common configuration engine. This engine uses
0498 ini files to get key/values from ini section (and subsection with inheritance).
0499 The configuration can point to directory and in that case Enduro/X will read the
0500 all configuration files in directory which ends with with ".ini .cfg, .conf, .config".
0501 Configuration engine will automatically detect that given resource is directory
0502 and will start to scan for files in directory.
0503 
0504 The library keeps all ini file data in memory in hash tables, which also can be iterated
0505 as the linked lists. The library can be instructed to refresh the memory configuration.
0506 Refresh function detects any files changed in disk (by time stamp) and reload the data
0507 in memory.
0508 
0509 === Enduro/X common configuration setup
0510 
0511 Enduro/X can be configured by using ini file (or files) instead of environment variables, 
0512 ndrxdebug.conf and q.conf.
0513 Two new environment variables now are added to the system:
0514 
0515 1. NDRX_CCONFIG=/path/to/ini/file/or/directory/with/files 
0516 
0517 2. And optional NDRX_CCTAG which allows processes to specify the subsection of 
0518 Enduro/X system settings.
0519 
0520 The configurations sections are:
0521 
0522 - [@global] - environment variables for process (see ex_env(5))
0523 
0524 - [@debug] - debug configuration per binary (see ndrxdebug.conf(5))
0525 
0526 - [@queue] - persistent queue configurations.
0527 
0528 If you use NDRX_CCTAG or specify the "cctag" for ATMI server, then Enduro/X 
0529 will scan for sections like (e.g. cctag=TAG1):
0530 
0531 - [@global/TAG1] and then [@global]
0532 
0533 - [@debug/TAG1] and then [@debug]
0534 
0535 - [@queue/TAG1] and then [@debug]
0536 
0537 cctag can contain multiple tags, which are separated by '/'.
0538 In that case multiple lockups will be made with base section combination.
0539 
0540 === User accessible configuration server
0541 
0542 "cconfsrv" XATMI server which can be used by applications to use Enduro/X 
0543 framework for application configuration. The user application can call the 
0544 "@CCONFIG" server in two modes:
0545 
0546 A) for getting the exact section;
0547 
0548 B) for listing the sections.
0549 
0550 See cconfsrv(8) for more details. 
0551 
0552 The idea behind this is that user can do the programming under Enduro/X in
0553  multiple languages (C/Go/Perl/Python/PHP/NodeJS) and these modules typically
0554 needs configuration. It would be waste of time if for each of the languages
0555 developer would need to think how to read the configuration from configuration
0556 files with native libraries. The Enduro/X offers standard XATMI micro-service 
0557 call for reading the ini files in common way for whole application,
0558 no matter in which language it is programmed.
0559 
0560 But C/C++ programmers can use Enduro/X direct libraries for configuration processing.
0561 See the 'atmitest/test029_inicfg/atmiclt29.c' for sample code.
0562 
0563 
0564 === Common configuration internals
0565 
0566 The configuration driving is built in multiple layers:
0567 
0568 - Layer 1: Physical file reading by "ini.h" library which gives the 
0569 callback for any parsed key/value/section;
0570 
0571 - Layer 2: Enduro/X code named "inicfg.h" and "inicfg.c". This drives the configuration
0572 object loads files into memory. Performs the refreshes, resolves the sections (with inheritance).
0573 Returns the buffers with values.
0574 
0575 - Layer 3: High level configuration driving by "cconfig.h" and "cconfig.c". This operates
0576 with Enduro/X environment variables and Enduro/X configuration files.
0577 However you may use different env variables for different purposes. For example:
0578 "NDRX_CCONFIG" variable can point to Enduro/X config, but "NDRX_CCONFIG1" can point to your
0579 application configuration. And this still is valid setup and keeps files separate.
0580 
0581 - Layer 4: "cconfsrv". This is high level API, accessible by transaction protocol (TP)
0582 sub-system. See the cconfsrv(8) manpage. Internally is uses Layer 2 and 3 API.
0583 
0584 [dia, common_config.dia, common_config.png, x450]
0585 -------------------------------
0586 -------------------------------
0587 
0588 == Common Debug logging API - TPLOG
0589 
0590 Enduro/X offer debug logging facility named "TPLOG". TPLog basically stands for extended
0591 user log. The user applications can use this API to configure TPLog, NDRX and UBF logs to
0592 be redirect to specified files, configure levels. Enduro/X introduces concept of request
0593 logging which means that each system request (or session) which processes UBF buffers can
0594 be logged to separate file. Which basically redirects NDRX, UBF and TPLog (user) to specific
0595 file. File can be set by *tplogsetreqfile(5)*.
0596 
0597 === Logging facilities  (topics)
0598 
0599 - 'NDRX', logging facility code 'N' - this is Enduro/X XATMI framework internal debug logging.
0600 Debug string setting for level is set with keyword 'ndrx'. Facility is defined with macros
0601 *LOG_FACILITY_NDRX*.
0602 
0603 - 'UBF', logging facility code 'U' - this is UBF library logs. In debug string
0604 level is set with keyword 'ubf'. Facility is defined with macros 'LOG_FACILITY_UBF'.
0605 
0606 - 'TP', logging facility code 't' - this is user logs. In debug string level is set with
0607 keyword 'tp'. Facility is defined with macros 'LOG_CODE_TP'. This is process based logging.
0608 
0609 - 'TP_THREAD', logging facility code 'T' - this is user logs, set on per thread basis. The log level
0610 is set with keyword 'tp'. Facility is defined with macros 'LOG_FACILITY_TP_THREAD'.
0611 
0612 - 'TP_REQUEST', logging facility code 'R' - this is user logs, set on 
0613 per thread/request basis. The log level is set with keyword 'tp'. 
0614 Facility is defined with macros 'LOG_FACILITY_TP_REQUEST'.
0615 
0616 - 'NDRX_THREAD', logging code 'n' - logs the Enduro/X internals on thread basis.
0617 
0618 - 'UBF_THREAD', logging code 'u' - logs UBF internals on thread basis.
0619 
0620 - 'NDRX_REQUEST', logging code 'm' - logs the Enduro/X internals on per request basis.
0621 
0622 - 'UBF_REQUEST', logging code 'v' - logs UBF internals on per request basis.
0623 
0624 Two objects are defined in the system: logger and file sink. When logger either
0625 process, thread or request opens then output file, firstly filename is checked in the
0626 hash list of file sinks (hashed by filename). If file name is found in hashlist,
0627 the the logger get the file sink object with the properties of *mkdir* and *bufsz*
0628 as they were configured for logger which actually opened the files (created file
0629 sink objects).
0630 
0631 If doing *$ xadmin logrotate*, then rotation is applied on file sinks and thus
0632 original *mkdir* and *bufsz* are used at point when files are open.
0633 
0634 
0635 === Hierarchy of the  loggers (facilities)
0636 
0637 The loggers output the debug content in following order of the facilities status
0638 (i.e. definition of current logger):
0639 
0640 - If 'TP_REQUEST' is open (debug file set), then all logging (TP) will go here.
0641 There will be no impact if 'TP_REQUEST' log level is different.
0642 The request logging can be open by *tplogsetreqfile(3)*. 
0643 Logger can be closed by *tplogclosereqfile(3)*.
0644 
0645 - If 'TP_THREAD' is open (debug file set), then all logs of TP will log here. 
0646 Thread logger can be open by doing
0647 *tplogconfig(LOG_FACILITY_TP_THREAD, ...)*. Thread logger can be 
0648 closed by *tplogclosethread(3)*
0649 
0650 - The above principles applies to NDRX_THREAD/REQUEST and UBF_THREAD/REQUEST too.
0651 
0652 - NOTE: That that Thread and request logger might have lower or the same 
0653 log levels as for main loggers. The higher log level than main log level will be
0654 ignored.
0655 
0656 If there is no TP_REQUEST or TP_THREAD facilities open, then logging is done on 
0657 per process basis, where there are 3 facilities which are always open:
0658 
0659 - 'NDRX', here XATMI sub-system is logged. It can be configured to use separate 
0660 file by *tplogconfig(3)*.
0661 
0662 - 'UBF', here UBF sub-system is logged. It can be configured to use separate 
0663 file by *tplogconfig(3)*.
0664 
0665 - 'TP', here TPLog sub-system is logged. It can be configured to use separate 
0666 file by *tplogconfig(3)*.
0667 
0668 
0669 === Debug string format
0670 
0671 The *debug string* format is described in *ndrxdebug.conf(5)* manpage. 
0672 basically it is following:
0673 
0674 - ndrx=<Debug level> ubf=<Debug level> tp=<Debug level> bufsz=<Number of 
0675 line to write after doing fflush> file=<log file name, if empty, then stderr>
0676 
0677 The debug level is one of the following:
0678 
0679 0. No logging output
0680 
0681 1. Fatal
0682 
0683 2. Error
0684 
0685 3. Warning 
0686 
0687 4. Program info
0688 
0689 5. Debug
0690 
0691 === Brief of logging functions
0692 
0693 Enduro/X debugging API offers following list of the functions:
0694 
0695 ==== Part of the standard library (ndebug.h)
0696 
0697 - void tplogdump(int 'lev', char *'comment', void *'ptr', int 'len'); - 
0698 Dumps the binary buffer (hex-dump) to current logger
0699 
0700 - void tplogdumpdiff(int 'lev', char *'comment', void *'ptr1', void *'ptr2', int 'len'); - 
0701 Compares two binary buffers and prints the hex-dump to current logger
0702 
0703 - void tplog(int 'lev', char *'message'); -
0704 Prints the message to current logger, at given log level
0705 
0706 - int tploggetreqfile(char *'filename', int 'bufsize'); - 
0707 Get the current request file (see the next chapter)
0708 
0709 - int tplogconfig(int 'logger', int 'lev', char *'debug_string', char *'module', 
0710 char *'new_file'); Configure logger. The loggers can be binary 'ored' and with 
0711 one function call multiple loggers can be configured. 'lev' is optional, if not 
0712 set it must be -1. Debug string is optional, but if have one then it can contain 
0713 all elements. 'module' is 4 symbols log module code using in debug lines. 
0714 'new_file' if set (not NULL and not EOS(0x00)) 
0715 then it have priority over the file present in debug string.
0716 
0717 - void tplogclosereqfile(void); -
0718 Close request file. The current logger will fall-back to either thread logger (if configured)
0719 or to process loggers.
0720 
0721 - void tplogclosethread(void); - 
0722 Close thread logger, if it was configured.
0723 
0724 - void tplogsetreqfile_direct(char *filename); -
0725 Set the request file, directly to logger. This operation is used by next function which
0726 allows to store the current request logging function in the XATMI UBF buffer.
0727 
0728 ==== Part of the XATMI library (xatmi.h)
0729 
0730 - int tplogsetreqfile(char **'data', char *'filename', char *'filesvc'); -
0731 Set the request file. If 'data' is UBF buffer allocated by *tpcalloc(3)*, then
0732 it will search for 'EX_NREQLOGFILE' field presence there. If field present,
0733 then 'TP_REQUEST' logger will be set to. If field not present, but 'filename' is 
0734 set (not NULL and not EOS),
0735 then request logger will be set to this file and name will be loaded into buffer.
0736 If file name is not in the buffer and not in the 'filename' but 'filesvc' present
0737 then this XATMI service will be called with 'data' buffer and it is expected 
0738 that field 'EX_NREQLOGFILE' will be set which then is used for logging.
0739 
0740 - int tploggetbufreqfile(char *'data', char *'filename', int 'bufsize'); -
0741 Get the request logging file name from XATMI buffer, basically this returns
0742 'EX_NREQLOGFILE' value.
0743 
0744 - int tplogdelbufreqfile(char *'data'); -
0745 Delete the request logging information from XATMI buffer.
0746 
0747 - void tplogprintubf(int 'lev', char *'title', UBFH *'p_ub'); - 
0748 print the UBF buffer to current logger.
0749 
0750 === Request logging concept
0751 
0752 Request logging is concept when each user session or transaction which is 
0753 processed by multiple XATMI clients and servers, are logged to single trace file.
0754 This is very useful when system have high load with request. Then administrators 
0755 can identify single transaction and with this request log file it is possible 
0756 to view full sequence of operation which system performed. You do not need anymore 
0757 to grep the big log files (based on each service output) and glue
0758 together the picture what have happened in system for particular transaction.
0759 
0760 The basic use of the request logging is following:
0761 
0762 Client process:
0763 --------------------------------------------------------------------------------
0764 
0765 /* read the request from network & parse
0766  * get the transaction subject (for example bank card number (PAN))
0767  * open the log file for each bank card request
0768  * e.g.
0769  */
0770 
0771 tplogsetreqfile(&p_ub, "/opt/app/logs/pan_based/<PAN>_<Time_stamp>", NULL);
0772 
0773 tplog("About to authorize");
0774 
0775 tpcall("AUTHORIZE", &p_ub, ...);
0776 
0777 /* reply to network */
0778 
0779 tplog("Transaction complete");
0780 
0781 /* close the logger after transaction complete */
0782 tplogclosereqfile();
0783 --------------------------------------------------------------------------------
0784 
0785 
0786 Server process - AUTHORIZE service
0787 --------------------------------------------------------------------------------
0788 void AUTHORIZE(TPSVCINFO *p_svc)
0789 {
0790     UBFH *p_ub = (UBFH *)p_svc->data;
0791 
0792     /* Just print the buffer */
0793     tplogsetreqfile((char **)&p_ub, NULL, NULL);
0794 
0795     tplogprintubf(log_debug, "AUTHORIZE got request", p_ub);
0796     
0797     tplog(log_debug, "Processing...!");
0798 
0799     /* do the work */
0800 
0801         /* close the request file as we are done. */    
0802     tplogclosereqfile();
0803 
0804     tpreturn(  TPSUCCESS,
0805                 0L,
0806                 (char *)p_ub,
0807                 0L,
0808                 0L);
0809 }
0810 --------------------------------------------------------------------------------
0811 
0812 
0813 Lest assume that for our transaction logfile is set to: 
0814 '/opt/app/logs/pan_based/5555550000000001_1475008709' then transaction could look like:
0815 
0816 [dia, reqlogging.dia, reqlogging.png, x300]
0817 -------------------------------
0818 -------------------------------
0819 
0820 === Understanding the format of log file
0821 
0822 For example given code:
0823 --------------------------------------------------------------------------------
0824 #include <ndebug.h>
0825 
0826 int main (int argc, char **argv)
0827 {
0828         tplog(5, "Hello from function logger");
0829         
0830         TP_LOG(log_debug, "Hello from macro logger [logging level %d]", log_debug);
0831 
0832         return 0;
0833 }
0834 --------------------------------------------------------------------------------
0835 
0836 Will print to log file following messages:
0837 
0838 --------------------------------------------------------------------------------
0839 t:USER:5:test1pc :11064:000:20160928:100225252:/tplog.c:0412:Hello from function logger
0840 t:USER:5:test1pc :11064:000:20160928:100225252:ogtest.c:0007:Hello from macro logger [logging level 5]
0841 --------------------------------------------------------------------------------
0842 
0843 So in general log line format is following:
0844 
0845 --------------------------------------------------------------------------------
0846 <LOGGER_FACILITY>:<MODULE>:<LOG_LEVEL>:<HOSCR>:<PID>:<OS_THREAD_ID>:<THREAD_ID>:<DATE>:<TIME_MS>:<SOURCE_FILE>:<LINE>:<MESSAGE>
0847 --------------------------------------------------------------------------------
0848 
0849 Where:
0850 
0851 - 'LOGGER_FACILITY' - is logger code which to which message is logged, i.e. 
0852 'N' - NDRX process based logger, 'U' - UBF process based logger, 
0853 't' - TP log, process based, 'T' - TP thread based logger, 'R' - TP request logger,
0854 'n' - Enduro/X internals (NDRX) thread logger, 'm' - Enduro/X internals (NDRX)
0855 request logger, 'u' - UBF thread logger, 'v' - UBF request logger.
0856 
0857 - 'MODULE' - 4 char long logger, 'NDRX' and 'UBF ' or user given code by 
0858 *tplogconfig(3)*. Default is 'USER'.
0859 
0860 - 'LOG_LEVEL' - message log level digit.
0861 
0862 - 'HOSTCR' - hostname crc32.
0863 
0864 - 'PID' - process id.
0865 
0866 - 'OS_THREAD_ID' - Operating system thread id (provided by libc or so).
0867 
0868 - 'THREAD_ID' - internal Enduro/X thread identifier.
0869 
0870 - 'DATE' - YYYYMMDD time stamp of the message (date part) in local TZ.
0871 
0872 - 'TIME_MS' - HHmmssSSS - time stamp of the message (time part) in local TZ.
0873 
0874 - 'SOURCE_FILE' - last 8 symbols of C/C++ source file from which macro logger was called.
0875 
0876 - 'LINE' - line number of the message in source code (where the macro logger was called).
0877 
0878 - 'MESSAGE' - logged user message.
0879 
0880 === XATMI server STDERR/STDOUT linking with the logger
0881 
0882 If XATMI server binary log file is set to *stderr* in *ndrxdebug.conf(5)* (either 
0883 file=/dev/stderr or empty file=) and *-e* flag is set in clopt for the XATMI
0884 server process, then process level loggers (*ndrx*/*ubf*/*tp*) also logs to this
0885 file. In such case if logrotate ("*xadmin(8)* lcf logrotate") is performed or
0886 process level logger file name is changed via *tplogconfig(3)*), then XATMI
0887 server's *stdout* and *stderr* is also re-directed to changed file name via
0888 *dup2()* Unix system call.
0889 
0890 == Queuing mechanisms
0891 
0892 This chapter describes different Enduro/X message transport mechanisms which are
0893 supported by Enduro/X. Enduro/X provides support for different transaction backends
0894 and there is no real difference for developer on which transport is used, except
0895 the performance and system resource administration aspects
0896 
0897 === Linux epoll, FreeBSD kqueue, AIX System V queue poll extension
0898 
0899 Enduro/X originally was developed for GNU/Linux kernels where resource polling sub-system
0900 i.e. epoll() can handle Posix queue handlers. This is linux non-standard feature which 
0901 greatly supports system development. FreeBSD operating system also supports polling
0902 and Posix queues. On IBM AIX there is support for poll() on System V queues.
0903 These polling features allows to build one queue - multiple servers
0904 architecture (even for ATMI server processes waiting on different set of queues). 
0905 However, this this feature limits platform to be working on Linux, FreeBSD and AIX
0906 only.
0907 
0908 [dia, epoll_message_dispatch_mode.dia, epoll_message_dispatch_mode.png, x300]
0909 -------------------------------
0910 -------------------------------
0911 
0912 Note there is a little overhead associated with IBM AIX, due to fact that Enduro/X
0913 uses string based queue identifiers, but System V queues are integers. Thus while
0914 operating in the same mode, for AIX two additional shared memory queue identifier 
0915 mapping tables are used which translate System V identifier to string and backwards.
0916 
0917 === System V mode
0918 
0919 Starting from Enduro/X version 6, there are added sub-system for System V IPC
0920 queues. With this supports, good performance almost the same as for Linux epoll mode.
0921 The mode is suitable for classical unixes such as Oracle Solaris.
0922 
0923 In case of System V mode, one-queue-multiple servers does not work for different
0924 set of services if advertised by binaries advertising also common services.
0925 
0926 Thus by default each XATMI server process opens it's own job request queue, and
0927 service requests are dispatched in round robin patter. How ever if set of binaries
0928 same set of queues, then it is possible to configure shared queue for these
0929 server processes. The shared queue is specified as "request address". 
0930 It defines one queue name on which all XATMI servers must advertise
0931 the same services.
0932 
0933 The implementation for System V is quite complicated, because these queues (
0934 see msgrcv(), msgsnd() system calls) does not offer any timeout control and
0935 secondly no form of polling on multiple queues are allowed. Thus these additional
0936 work semantics must be emulated.
0937 
0938 Common approaches for *XATMI clients and servers* are following:
0939 
0940 . System V message queue IDs are mapped to string for queue names, which are
0941 used internally by Enduro/X. The mapping is done in two new shared memory segments
0942 whose size is controlled by *NDRX_MSGQUEUESMAX* environment variable, see ex_env(5).
0943 
0944 . The timeouts are controlled by one new additional thread - event thread, 
0945 to which receives list of queues to monitor for timeout via shared hash structure
0946 or via unnamed pipe (only for processes with having also file descriptors monitored
0947 in XATMI servers). The even thread wakes up every second and scan the hash list
0948 for time-outs. If time-out is found and main thread which did queue
0949 operation is still in the queue call, it is interrupted by pthread_kill() system
0950 call. There are timestamp and sequence markers for each blocked System V IPC
0951 queue calls, so that timeout knows that man thread is in particular state, and
0952 have not reached the next call. If main thread has been woken up, then timeout
0953 is discarded once reached. Event thread performs timed poll on unnamed pipe, so
0954 that it is blocked till calculated next wake-up/timeout.
0955 
0956 . Special care shall be taken when process forking is required. As event thread
0957 is common for XATMI servers and clients, the fork by main thread will terminate
0958 those threads at un-determined point. Thus if new process wishes to continue
0959 to operate with XATMI session special approaches shall be done when forking
0960 Enduro/X processes. See sections in text regarding process forking.
0961 
0962 For *XATMI servers* the approach is further extended, so that:
0963 
0964 . There is one more additional thread listening for admin messages (i.e. pings
0965 and shutdowns). Once the message is received, it is placed in internal queue for
0966 the main server poller queue. If main thread is in blocked state of System V queue,
0967 it is waken up by pthread_kill(). If main thread was doing something else, then
0968 before doing next System V message receive, it checks the internal message queue
0969 and picks up the admin message from there.
0970 
0971 . As Enduro/X provides extensions for file descriptor polling, System V interfaces
0972 provides this API too. The user file extensions are put in the even thread's 
0973 poll() structure. If event is noticed on user file descriptor, the event is sent
0974 to corresponding main thread and during that time, the file descriptor is removed
0975 from event thread, because otherwise it will signal again that there is something
0976 on the user FD (as main and even threads are async, and even thread might run
0977 faster than main thread). Thus user FD is enabled for polling only when main thread
0978 returns after the processing back to waiting for message.
0979 
0980 
0981 [dia, systemv_message_dispatch_mode.dia, systemv_message_dispatch_mode.png, x500]
0982 -------------------------------
0983 ------------------------------- 
0984 
0985 === Poll mode
0986 
0987 Starting from Enduro/X version 3, there is support for other Posix compatible 
0988 Operating Systems. Where possible Posix queues are used. If no Queue support 
0989 built in, for example Apple OSX, then emulated Posix queues are used. 
0990 For these platforms, the caller processes does choose the queue where to 
0991 send the message in round-robin mode. For each service shared memory 
0992 contains list of server IDs providing the service. In round robin mode the 
0993 server id is selected, and caller sends the service to
0994 queue (e.g. 'dom1,svc,TESTSVC,102' where '102' is server id.).
0995 
0996 [dia, poll_message_dispatch_mode.dia, poll_message_dispatch_mode.png, x450]
0997 -------------------------------
0998 -------------------------------
0999 
1000 For other unix support, mq_notify() call for each open queue is installed, 
1001 by employing SIGUSR2. Signal handling is done in separate thread. The main 
1002 ATMI server thread is doing 'poll()' in unnamed pipe. When event from mq_ 
1003 sub-system is received, it writes the queue descriptor id to unnamed pipe 
1004 and that makes main thread to wake up for queue processing. The 'poll()' for 
1005 main thread supports Enduro/X extensions to add some other resource for
1006 polling (e.g. socket fd.)
1007 
1008 
1009 == Multi-threading
1010 
1011 Enduro/X supports multit-threading. For example all XATMI APIs are thread
1012 safe. The UBF APIs are thread safe while the two threads does not operate with
1013 the same UBF buffer. User code can do the multi-threading as required. Each
1014 new thread which starts to operate with XATMI API, joins to the system as
1015 XATMI client.
1016 
1017 === Thread stack sizes
1018 
1019 Enduro/X may create threads for processes such as *tpbridge(8)*, *tmsrv(8)*, in case if
1020 using XATMI Server dispatch threads, System V mode, etc. 
1021 In general in case if Enduro/X is creating thread internally, the following strategy is applied:
1022 
1023 . The Enduro/X thread stack size maybe set by help of *NDRX_THREADSTACKSIZE*.
1024 
1025 . If *NDRX_THREADSTACKSIZE* is missing, getrlimit(), *RLIMIT_STACK* call is used
1026 to determine main thread stack size. 
1027 
1028 . If above does not succeed, the new thread stack size is set to 8 MB.
1029 
1030 === XATMI Server dispatch thread pool
1031 
1032 The Enduro/X also comes with support of XATMI server thread call dispatch thread pool support.
1033 This means that developers can write multi-threaded (MT) server programs with very
1034 little to non additional effort. If MT is configured (*ndrxconfig.xml(5)*
1035 setting *<maxdispatchthreads>* is set greater than *1* and *<mindispatchthreads>* 
1036 denotest the actual number of worker threads), the XATMI servers at
1037 startup will create pool of configured number of worker threads. Thus when server's
1038 main thread will receive the message, the message is immediately passed to the
1039 thread pool. And at next step main thread goes back for waiting to the messages.
1040 
1041 Before main thread start to wait for next message, it ensures that at least one
1042 worker thread is free, otherwise the server process will just copy all messages
1043 from IPC queues to internal thread pool job queue. That would result in loss
1044 of load balancing between processes.
1045 
1046 If server threading is configured, the start up initialization sequence looks like this:
1047 
1048 . INIT: *tpsvrinit(3)* is invoked for main thread.
1049 
1050 . INIT: *tpsvrthrinit(3)* is invoked for each dispatching worker thread. Before function call
1051 each worker thread is initialized as XATMI client.
1052 This is special XATMI client, it has access to perform the work in name of the
1053 main server thread. Once initialized, the threads become parked on internal job queue.
1054 
1055 . OPER: main thread read the XATMI queues and puts the in job queue for worker threads.
1056 
1057 . OPER: main thread waits for one free worker thread.
1058 
1059 . OPER: main thread continue with XATMI queues read.
1060 
1061 . SHUTDOWN: *tpsvrdone(3)* is called for main thread.
1062 
1063 . SHUTDOWN: *tpsvrthrdone(3)* is called for each worker thread. After the function returns,
1064 *tpterm(3)* is invoked for threads.
1065 
1066 To enable multi-thread mode, binaries must be specifically built for this. This may be
1067 done by passing the *-t* flag to *buildserver(8)* compiler tool, or by setting
1068 *_tmbuilt_with_thread_option* extern variable to *1* before running ndrx_main_integra(),
1069 ndrx_main() or _tmstartserver(). If flag is not configured, binary will start
1070 in single-thread mode and warning will be printed to ULOG. The error would look like:
1071 
1072 --------------------------------------------------------------------------------
1073 
1074 05828:20200503:23031209:atmi.sv1    :Warning ! Server not built for mulit-threading, but MINDISPATCHTHREADS=2 MAXDISPATCHTHREADS=2, falling back to single thread mode
1075 
1076 --------------------------------------------------------------------------------
1077 
1078 *tpsvrthrinit(3)* and  *tpsvrthrdone(3)* may be specified only in case if string
1079 from _tmstartserver().
1080 
1081 Configuration example:
1082 
1083 --------------------------------------------------------------------------------
1084 
1085     <server name="atmi.sv1">
1086             <srvid>1400</srvid>
1087             <min>1</min>
1088             <max>1</max>
1089             <mindispatchthreads>5</mindispatchthreads>
1090             <maxdispatchthreads>5</maxdispatchthreads>
1091             <sysopt>-e /tmp/ATMISV1 -r</sysopt>
1092     </server>
1093 
1094 --------------------------------------------------------------------------------
1095 
1096 === Infinite server (daemon) construction
1097 
1098 Enduro/X XATMI server multi-threading model supports infinit server mode. That is during
1099 the tpsvrinit() tpsvrthrinit() it is possible to do calls to self-advertised services with help
1100 of *tpacall*('SELF_SERVICE',...,*TPNOREPLY*). In this case after all init is done, 
1101 but before main thread goes in waiting for messages, these *tpacall(3)* messages are injected into service
1102 queues. Thus dispatcher will wake up and will process the message by worker thread. The worker
1103 thread may become busy for infinite time (loop). And for example other thread service 
1104 functions may be used to control the daemon thread.
1105 
1106 
1107 === Server threading limitations
1108 
1109 . If file descriptors callbacks added by *tpext_addpollerfd(3)*, then any file 
1110 descriptor events are processed by main thread.
1111 
1112 . *tpadvertise(3)* and *tpunadvertise(3)* functions are during the service calls. 
1113 These functions are available during the tpsvrinit() and tpsvrthrinit() phases.
1114 
1115 
1116 === Additional multi-thread notes
1117 
1118 . Developer is free to implement any other multi-threading operations in the binaries.
1119 The server dispatcher mechanisms is provided only for simplicity of building
1120 multi-threaded servers.
1121 
1122 
1123 == Fast Pool Allocator
1124 
1125 Enduro/X uses dynamic memory for storing temporary internal messages. For
1126 performance reasons dynamic memory allocated memory blocks are being cached so
1127 that they can be re-used, instead of requesting malloc() and then free() again.
1128 I.e. if there are no entries in cache, then malloc() is issued. When Enduro/X is
1129 doing block free, cache is tested, if there are less block than minimum cached,
1130 then block is added to linked list of free blocks. If there are enough cached
1131 blocks, the block is processed by standard free() call.
1132 
1133 The cache size can be configured by setting *NDRX_FPAOPTS* environment variable
1134 (see ex_env(5)*). The variable may override default settings for the block cache.
1135 
1136 Block cache is set for following sizes (with default nr of blocks cached in scopes):
1137 
1138 . 256 bytes (25 blocks).
1139 
1140 . 512 bytes (15 blocks).
1141 
1142 . 1024 bytes (10 blocks).
1143 
1144 . 2048 bytes (10 blocks).
1145 
1146 . 4096 bytes (10 blocks).
1147 
1148 . 8192 bytes (10 blocks).
1149 
1150 . System buffer size set in *NDRX_MSGMAX* (10 blocks).
1151 
1152 The sizes may be changed by *NDRX_FPAOPTS* environment variable value. See *ex_env(5)*
1153 for syntax.
1154 
1155 
1156 == Object-API
1157 
1158 Enduro/X provides Object API functions. This is meant to be used with integration 
1159 into programming languages and frameworks, where cooperative multi-threading 
1160 is used. This API also is suitable for systems like Node.JS where system call, 
1161 e.g. C lang call can result in different operating system thread. This fact 
1162 can cause lot of issues, for example, in cooperative multi-threading two 
1163 concurrent 'tpacall()' requests can return results for different cooperative 
1164 threads, which will cause them to drop the
1165 response and both calls with might finish with time-out.
1166 
1167 
1168 Thus Enduro/X provides following header files for Object-API:
1169 
1170 - odebug.h - ATMI Object based debugging
1171 
1172 - oubf.h - ATMI Object based UBF operations
1173 
1174 - oatmi.h - ATMI operations via ATMI Object
1175 
1176 - oatmisrv.h - ATMI server operations via ATMI Object.
1177 
1178 
1179 The API basically consists of all UBF and ATMI functions, they are prefixed 
1180 with letter 'O' and as first parameter all of them consume 'TPCONTEXT_T' typed
1181 parameter. Which basically is pointer to heap stored ATMI Object.
1182 This ATMI Object also includes links to Standard library and UBF 
1183 library heap allocated objects.
1184 
1185 Every Object-API function basically does following:
1186 
1187 1. Set (call of 'tpsetctxt()') the current thread TLS to passed in context;
1188 
1189 2. Call the actual UBF/ATMI function;
1190 
1191 3. Unset/get (call of 'tpsetctxt()') the thread local data;
1192 
1193 
1194 During the Enduro/X C library works, it is assumed that is not preemptive for 
1195 cooperative threads. Thus above scheme will work for every framework that comply 
1196 with rule (and mostly it does, because it will break the rules of 
1197 library C/C++ processing).
1198 
1199 The typical code for Object API would be following:
1200 
1201 --------------------------------------------------------------------------------
1202 #include <string.h>
1203 #include <stdio.h>
1204 #include <stdlib.h>
1205 
1206 #include <oatmi.h>
1207 #include <oubf.h>
1208 #include <odebug.h>
1209 #include <Exfields.h>
1210 
1211 int main(int argc, char **argv)
1212 {
1213     int ret = 0;
1214     int cd1;
1215     UBFH *p_ub1;
1216     long rsplen;
1217     /* Allocate new context aka Object */
1218     TPCONTEXT_T ctx1 = tpnewctxt();
1219 
1220     /* Initialise client session */
1221     if (SUCCEED!=Otpinit(&ctx1, NULL))
1222     {
1223         /* print the thread based logs */
1224         ONDRX_LOG(&ctx1, log_error, "TESTERROR: Failed to Otpinit 1: %s",
1225                     Otpstrerror(&ctx1, Otperrno(&ctx1)));
1226         ret = -1;
1227         goto out;
1228     }
1229 
1230     /*Do some client based logging */
1231     ONDRX_LOG(&ctx1, log_always, "Hello from CTX1");
1232 
1233     if (NULL==(p_ub1 = (UBFH *)Otpalloc(&ctx1, "UBF", NULL, 8192)))
1234     {
1235         ONDRX_LOG(&ctx1, log_error, "TESTERROR: Failed to Otpalloc ub1: %s",
1236                     Otpstrerror(&ctx1, Otperrno(&ctx1)));
1237         ret = -1;
1238         goto out;
1239     }
1240 
1241     /* set some buffer value */
1242     if (SUCCEED!=OCBchg(&ctx1, p_ub1, EX_CC_CMD, 0, "l", 0L, BFLD_STRING))
1243     {
1244         ONDRX_LOG(&ctx1,log_error, "TESTERROR: OCBchg() failed %s", 
1245                 OBstrerror(&ctx1, OBerror(&ctx1)));
1246         ret = -1;
1247         goto out;
1248    }
1249 
1250     /* call the server */
1251     if (FAIL==Otpcall(&ctx1, "SOMESVC", (char *)p_ub1, 0L, (char **)&p_ub1, &rsplen, 0L))
1252     {
1253         ONDRX_LOG(&ctx1, log_error, "TESTERROR: Failed to Otpcall 1: %s", 
1254                 Otpstrerror(&ctx1, Otperrno(&ctx1)));
1255         ret = -1;
1256         goto out;
1257     }
1258 
1259     /* free the buffer */
1260     Otpfree(&ctx1, (char *)p_ub1);
1261 
1262 
1263     /* terminate ATMI client session */
1264     if (SUCCEED!=Otpterm(&ctx1))
1265     {
1266         ONDRX_LOG(&ctx1, log_error, "TESTERROR: Failed to terminate client 1", 
1267                 Otpstrerror(&ctx1, Otperrno(&ctx1)));
1268         ret = -1;
1269         goto out;
1270     }
1271 
1272     /* free the NSTD/UBF/ATMI objects */
1273     tpfreectxt(ctx1);
1274 
1275 out:
1276     return ret;
1277 
1278 }
1279 --------------------------------------------------------------------------------
1280 
1281 Build with:
1282 --------------------------------------------------------------------------------
1283 $ gcc test.c  -latmi -lubf -lnstd -lpthread -lrt -lm -ldl
1284 --------------------------------------------------------------------------------
1285 
1286 See atmitest/test032_oapi/atmiclt32.c for more sample code.
1287 
1288 === Class model
1289 
1290 For programming languages that supports classes or objects, following class model
1291 will be used for Enduro/X bindings. 
1292 
1293 [dia, class_diagram.dia, class_diagram.png, x300]
1294 -------------------------------
1295 -------------------------------
1296 
1297 This diagram is based on 'endurox-go' package, which uses structures and special
1298 functions that are binded to structure. Basically that is the same as classes.
1299 
1300 This model might be implemented for Node.js and Platform Script.
1301 
1302 
1303 == Generating source code with Enduro/X generators
1304 
1305 Enduro/X xadmin command line utility comes with built in generators. Currently
1306 following generator targets are available:
1307 
1308 - *ubf tab* - Generate 'UBF' table header files. This target can generate include file
1309 for C, or Go package which constants of the field definitions.
1310 
1311 - *c server* - Generate C server. The server can have a common configuration. Wizard
1312 offers some options like building a makefile and using a UBF buffer.
1313 
1314 - *c client* - Generate C client application. This make sample C client app 
1315 which in case if UBF buffer is select for data buffer, the sample call 
1316 is made to *TESTSV* XATMI service.
1317 
1318 - *go server* - Go server which depends on *endurox-go* package.
1319 Thus in project path the endurox-go package must be installed. 
1320 (See the sample bellow).
1321 
1322 - *go client* - Generate Go XATMI client process. As with Go server, 
1323 it requires that endurox-go is installed in project path. 
1324 That can be done by  $ go get https://github.com/endurox-dev/endurox-go
1325 
1326 The target can be invoked by running $ xadmin gen <target>, for example:
1327 
1328 --------------------------------------------------------------------------------
1329 
1330 $ xadmin gen c server
1331 Enduro/X 3.4.3, build Feb 10 2017 00:34:28, using poll for DARWIN (64 bits)
1332 
1333 Enduro/X Middleware Platform for Distributed Transaction Processing
1334 Copyright (C) 2015, 2016 Mavimax, Ltd. All Rights Reserved.
1335 
1336 This software is released under one of the following licenses:
1337 GPLv2 (or later) or Mavimax's license for commercial use.
1338 
1339  0: srvname      :XATMI Server Name (binary) [testsv]:
1340  1: svcnm        :Service name [TESTSV]:
1341  2: useubf       :Use UBF? [y]: n
1342  4: genmake      :Gen makefile [y]:
1343 
1344 *** Review & edit configuration ***
1345 
1346  0: Edit srvname      :XATMI Server Name (binary) [testsv]:
1347  1: Edit svcnm        :Service name [TESTSV]:
1348  2: Edit useubf       :Use UBF? [n]:
1349  4: Edit genmake      :Gen makefile [y]:
1350 c: Cancel
1351 w: Accept, write
1352 Enter the choice [0-5, c, w]: w
1353 C server gen ok!
1354 
1355 $ make
1356 cc -c -o testsv.o testsv.c -I../ubftab
1357 cc -o testsv  testsv.o -latmisrvinteg -latmi -lubf -lnstd -lpthread -ldl -lm
1358 $
1359 --------------------------------------------------------------------------------
1360 
1361 Xadmin's package also includes provision scripts which will setup runtime quickly. The
1362 command is '$ xadmin provision'.
1363 
1364 === Implementing custom generators
1365 
1366 Enduro/X *xadmin* can be configured with custom generators. The directory or script
1367 file name where xadmin looks for Platform Scripts, are configured with following
1368 configuration resources:
1369 
1370 1. Search by *NDRX_XADMIN_CONFIG* environment variable.
1371 
1372 2. Search *~/.xadmin.config*
1373 
1374 3. Search */etc/xadmin.config*
1375 
1376 Use first one found. Searches *[xadmin/<CCTAG>]* section. uses parameter *gen scripts=*.
1377 This indicates the folder where to list the *.pscript* generator files.
1378 
1379 For sample file, see Enduro/X *xadmin/scripts/gen_c_client.pscript* generator in source code.
1380 
1381 
1382 === Building sample application generators
1383 
1384 In this section we will make an application where C client code will 
1385 invoke Go server. The IPC will use UBF buffer, with test fields which are provided
1386 by *ubf tab* generator. Also this example assumes that you have installed enduro/x
1387 and endurox-go packages to your system and kernel parameters are configured (e.g.
1388 queue settings in case of Linux).
1389 
1390 ==== Prepare project folder3
1391 
1392 Lets assume our project will be made at $TESTHOME. The sources (with
1393 sub-projects) will go under $TESTHOME/src. This structure is required
1394 for Go projects. For Linux operating system we will set $TESTHOME to */home/user1/app2*.
1395 
1396 --------------------------------------------------------------------------------
1397 # useradd -m user1
1398 # su - user1
1399 $ mkdir /home/user1/app2
1400 $ export TESTHOME=/home/user1/app2
1401 $ mkdir $TESTHOME/src
1402 --------------------------------------------------------------------------------
1403 
1404 ==== Generate UBF table for both C & Go
1405 
1406 The application will communicate via Unified Buffer Format (*UBF*) buffer. The
1407 test field definitions will be used for this application. Firstly lets generate C
1408 headers:
1409 
1410 --------------------------------------------------------------------------------
1411 $ mkdir $TESTHOME/src/ubftab
1412 $ cd $TESTHOME/src/ubftab
1413 
1414 $ xadmin gen ubf tab
1415 Enduro/X 3.4.3, build Feb 10 2017 00:26:22, using epoll for LINUX (64 bits)
1416 
1417 Enduro/X Middleware Platform for Distributed Transaction Processing
1418 Copyright (C) 2015, 2016 Mavimax, Ltd. All Rights Reserved.
1419 
1420 This software is released under one of the following licenses:
1421 GPLv2 (or later) or Mavimax's license for commercial use.
1422 
1423 Logging to ./ULOG.20170211
1424  0: table_name   :UBF Table name (.fd will be added) [test]: 
1425  1: base_number  :Base number [6000]: 
1426  2: testfields   :Add test fields [y]: 
1427  3: genexfields  :Gen Exfields [y]: 
1428  4: genmake      :Gen makefile [y]: 
1429  5: makeLang     :Target language (c/go) [c]: 
1430 
1431 *** Review & edit configuration ***
1432 
1433  0: Edit table_name   :UBF Table name (.fd will be added) [test]: 
1434  1: Edit base_number  :Base number [6000]: 
1435  2: Edit testfields   :Add test fields [y]: 
1436  3: Edit genexfields  :Gen Exfields [y]: 
1437  4: Edit genmake      :Gen makefile [y]: 
1438  5: Edit makeLang     :Target language (c/go) [c]: 
1439 c: Cancel
1440 w: Accept, write
1441 Enter the choice [0-6, c, w]: w
1442 Gen ok!
1443 
1444 $
1445 
1446 --------------------------------------------------------------------------------
1447 
1448 Now we see that 'test.fd.h' is generate. Lets generate Go definitions. Before that
1449 we will set 'GOPATH' to project root.
1450 
1451 --------------------------------------------------------------------------------
1452 $ cd $TESTHOME
1453 $ export GOPATH=`pwd`
1454 $ cd $TESTHOME/src/ubftab
1455 $ xadmin gen ubf tab
1456 Enduro/X 3.4.3, build Feb 10 2017 00:26:22, using epoll for LINUX (64 bits)
1457 
1458 Enduro/X Middleware Platform for Distributed Transaction Processing
1459 Copyright (C) 2015, 2016 Mavimax, Ltd. All Rights Reserved.
1460 
1461 This software is released under one of the following licenses:
1462 GPLv2 (or later) or Mavimax's license for commercial use.
1463 
1464 Logging to ./ULOG.20170211
1465  0: table_name   :UBF Table name (.fd will be added) [test]: 
1466  1: base_number  :Base number [6000]: 
1467  2: testfields   :Add test fields [y]: 
1468  3: genexfields  :Gen Exfields [y]: 
1469  4: genmake      :Gen makefile [y]: 
1470  5: makeLang     :Target language (c/go) [c]: go
1471 
1472 *** Review & edit configuration ***
1473 
1474  0: Edit table_name   :UBF Table name (.fd will be added) [test]: 
1475  1: Edit base_number  :Base number [6000]: 
1476  2: Edit testfields   :Add test fields [y]: 
1477  3: Edit genexfields  :Gen Exfields [y]: 
1478  4: Edit genmake      :Gen makefile [y]: 
1479  5: Edit makeLang     :Target language (c/go) [go]: 
1480 c: Cancel
1481 w: Accept, write
1482 Enter the choice [0-6, c, w]: w
1483 Gen ok!
1484 
1485 $
1486 --------------------------------------------------------------------------------
1487 
1488 
1489 Once the files are generated, we can run off the make:
1490 
1491 --------------------------------------------------------------------------------
1492 
1493 $ cd $TESTHOME/src/ubftab
1494 
1495 $ make
1496 make -f Mclang
1497 $SOURCES is [./test.fd Exfields]
1498 $OUTPUT is [./test.fd.h Exfields.h]
1499 $FIELDTBLS is [./test.fd,Exfields]
1500 make[1]: Entering directory `$TESTHOME/src/ubftab'
1501 mkfldhdr -m0 -pubftab
1502 To control debug output, set debugconfig file path in $NDRX_DEBUG_CONF
1503 N:NDRX:5:  732:2ae627e394c0:000:20170211:163548263:fldhdr.c:0229:Output directory is [.]
1504 N:NDRX:5:  732:2ae627e394c0:000:20170211:163548263:fldhdr.c:0230:Language mode [0]
1505 N:NDRX:5:  732:2ae627e394c0:000:20170211:163548263:fldhdr.c:0231:Private data [ubftab]
1506 N:NDRX:5:  732:2ae627e394c0:000:20170211:163548263:fldhdr.c:0243:Use environment variables
1507 U:UBF :5:  732:2ae627e394c0:000:20170211:163548263:dtable.c:0114:Using NDRX_UBFMAXFLDS: 16000
1508 N:NDRX:5:  732:2ae627e394c0:000:20170211:163548263:fldhdr.c:0303:enter generate_files()
1509 U:UBF :5:  732:2ae627e394c0:000:20170211:163548263:fldhdr.c:0138:Load field dir [$TESTHOME/src/ubftab]
1510 U:UBF :5:  732:2ae627e394c0:000:20170211:163548263:fldhdr.c:0149:About to load fields list [./test.fd,Exfields]
1511 N:NDRX:5:  732:2ae627e394c0:000:20170211:163548264:fldhdr.c:0369:$TESTHOME/src/ubftab/./test.fd processed OK, output: ./test.fd.h
1512 N:NDRX:5:  732:2ae627e394c0:000:20170211:163548264:fldhdr.c:0369:$TESTHOME/src/ubftab/Exfields processed OK, output: ./Exfields.h
1513 N:NDRX:5:  732:2ae627e394c0:000:20170211:163548264:fldhdr.c:0256:Finished with : SUCCESS
1514 make[1]: Leaving directory `$TESTHOME/src/ubftab'
1515 make -f Mgolang
1516 $SOURCES is [./test.fd Exfields]
1517 $OUTPUT is [./test.fd.go Exfields.go]
1518 $FIELDTBLS is [./test.fd,Exfields]
1519 make[1]: Entering directory `$TESTHOME/src/ubftab'
1520 mkfldhdr -m1 -pubftab
1521 To control debug output, set debugconfig file path in $NDRX_DEBUG_CONF
1522 N:NDRX:5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0229:Output directory is [.]
1523 N:NDRX:5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0230:Language mode [1]
1524 N:NDRX:5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0231:Private data [ubftab]
1525 N:NDRX:5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0243:Use environment variables
1526 U:UBF :5:  736:2aad91d474c0:000:20170211:163548271:dtable.c:0114:Using NDRX_UBFMAXFLDS: 16000
1527 N:NDRX:5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0303:enter generate_files()
1528 U:UBF :5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0138:Load field dir [$TESTHOME/src/ubftab]
1529 U:UBF :5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0149:About to load fields list [./test.fd,Exfields]
1530 N:NDRX:5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0369:$TESTHOME/src/ubftab/./test.fd processed OK, output: ./test.fd.go
1531 N:NDRX:5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0369:$TESTHOME/src/ubftab/Exfields processed OK, output: ./Exfields.go
1532 N:NDRX:5:  736:2aad91d474c0:000:20170211:163548271:fldhdr.c:0256:Finished with : SUCCESS
1533 go build  -o ubftab *.go
1534 go install  ./...
1535 make[1]: Leaving directory `$TESTHOME/src/ubftab'
1536 
1537 $ ls -l
1538 total 72
1539 -rw-rw-r-- 1 user1 user1  9641 feb 11 16:25 Exfields
1540 -rw-rw-r-- 1 user1 user1  6079 feb 11 16:35 Exfields.go
1541 -rw-rw-r-- 1 user1 user1  7614 feb 11 16:35 Exfields.h
1542 -rw-rw-r-- 1 user1 user1   145 feb 11 16:25 Makefile
1543 -rw-rw-r-- 1 user1 user1   492 feb 11 16:25 Mclang
1544 -rw-rw-r-- 1 user1 user1   562 feb 11 16:27 Mgolang
1545 -rw-rw-r-- 1 user1 user1  1301 feb 11 16:25 test.fd
1546 -rw-rw-r-- 1 user1 user1  1532 feb 11 16:35 test.fd.go
1547 -rw-rw-r-- 1 user1 user1  1999 feb 11 16:35 test.fd.h
1548 -rw-rw-r-- 1 user1 user1  2882 feb 11 16:35 ubftab
1549 -rw-rw-r-- 1 user1 user1 15464 feb 11 16:27 ULOG.20170211
1550 
1551 $ head -n10 test.fd.h 
1552 #ifndef __TEST_FD
1553 #define __TEST_FD
1554 /*      fname   bfldid            */
1555 /*      -----   -----            */
1556 #define T_CHAR_FLD      ((BFLDID32)67114875)    /* number: 6011  type: char */
1557 #define T_CHAR_2_FLD    ((BFLDID32)67114876)    /* number: 6012  type: char */
1558 #define T_SHORT_FLD     ((BFLDID32)6021)        /* number: 6021  type: short */
1559 #define T_SHORT_2_FLD   ((BFLDID32)6022)        /* number: 6022  type: short */
1560 #define T_LONG_FLD      ((BFLDID32)33560463)    /* number: 6031  type: long */
1561 #define T_LONG_2_FLD    ((BFLDID32)33560464)    /* number: 6032  type: long */
1562 
1563 --------------------------------------------------------------------------------
1564 
1565 So it have installed a 'ubftab' package, and generated 'test.fd.h' file.
1566 
1567 
1568 ==== Generate C client code & make
1569 
1570 Now lets generate a C client code which will send the UBF buffer to Go server.
1571 The generator provides C sample client, let's use it.
1572 
1573 --------------------------------------------------------------------------------
1574 $ mkdir $TESTHOME/src/clt
1575 $ cd $TESTHOME/src/clt
1576 
1577 $ xadmin gen c client
1578 Enduro/X 3.4.3, build Feb 10 2017 00:26:22, using epoll for LINUX (64 bits)
1579 
1580 Enduro/X Middleware Platform for Distributed Transaction Processing
1581 Copyright (C) 2015, 2016 Mavimax, Ltd. All Rights Reserved.
1582 
1583 This software is released under one of the following licenses:
1584 GPLv2 (or later) or Mavimax's license for commercial use.
1585 
1586 Logging to ./ULOG.20170211
1587  0: cltname      :XATMI Client Name (binary) [testcl]: 
1588  1: useubf       :Use UBF? [y]: 
1589  2: ubfname      :UBF include folder name (will be done ../<name>) [ubftab]: 
1590  3: genmake      :Gen makefile [y]: 
1591  4: config       :INI File section (optional, will read config if set) []: 
1592 
1593 *** Review & edit configuration ***
1594 
1595  0: Edit cltname      :XATMI Client Name (binary) [testcl]: 
1596  1: Edit useubf       :Use UBF? [y]: 
1597  2: Edit ubfname      :UBF include folder name (will be done ../<name>) [ubftab]: 
1598  3: Edit genmake      :Gen makefile [y]: 
1599  4: Edit config       :INI File section (optional, will read config if set) []: 
1600 c: Cancel
1601 w: Accept, write
1602 Enter the choice [0-4, c, w]: w
1603 C client gen ok!
1604 
1605 
1606 $ make
1607 cc -c -o testcl.o testcl.c -I../ubftab
1608 cc -o testcl  testcl.o -latmiclt -latmi -lubf -lnstd -lpthread -lrt -ldl -lm
1609 --------------------------------------------------------------------------------
1610 
1611 C Client have been generated OK and built ok.
1612 
1613 ==== Generate Go server code & make
1614 
1615 Now lets generate Go server. Before we make the Go app, we need to get the
1616 *endurox-go* package.
1617 
1618 --------------------------------------------------------------------------------
1619 $ cd $TESTHOME
1620 $ go get github.com/endurox-dev/endurox-go
1621 $ mkdir $TESTHOME/src/srv
1622 $ cd $TESTHOME/src/srv
1623 $ xadmin gen go server
1624 Enduro/X 3.4.4, build Feb 11 2017 16:57:21, using epoll for LINUX (64 bits)
1625 
1626 Enduro/X Middleware Platform for Distributed Transaction Processing
1627 Copyright (C) 2015, 2016 Mavimax, Ltd. All Rights Reserved.
1628 
1629 This software is released under one of the following licenses:
1630 GPLv2 (or later) or Mavimax's license for commercial use.
1631 
1632 Logging to ./ULOG.20170211
1633  0: svname       :XATMI Server Name (binary) [testsv]: 
1634  1: svcname      :Service name [TESTSV]: 
1635  2: useubf       :Use UBF? [y]: 
1636  3: ubfname      :UBF package name [ubftab]: 
1637  4: genmake      :Gen makefile [y]: 
1638  5: config       :INI File section (optional, will read config if set) []: 
1639 
1640 *** Review & edit configuration ***
1641 
1642  0: Edit svname       :XATMI Server Name (binary) [testsv]: 
1643  1: Edit svcname      :Service name [TESTSV]: 
1644  2: Edit useubf       :Use UBF? [y]: 
1645  3: Edit ubfname      :UBF package name [ubftab]: 
1646  4: Edit genmake      :Gen makefile [y]: 
1647  5: Edit config       :INI File section (optional, will read config if set) []: 
1648 c: Cancel
1649 w: Accept, write
1650 Enter the choice [0-5, c, w]: w
1651 Go server gen ok!
1652 
1653 
1654 $ make
1655 go build  -o testsv *.go
1656 --------------------------------------------------------------------------------
1657 
1658 As we see test server was built ok. Now next step is to configure a runtime system.
1659 With provisioning of the configuration files and adding testsv to boot application
1660 boot sequence.
1661 
1662 ==== Provision runtime and put binaries symlinks
1663 
1664 To create a runtime system, we will use $ xadmin provision command. This command
1665 allows to register one server to ndrxconfig.xml. For demo application purposes
1666 this is fully fine. The provision will be done in root directly of "bankapp2".
1667 
1668 
1669 --------------------------------------------------------------------------------
1670 $ cd $TESTHOME
1671 
1672 
1673 $ ls -l
1674 total 8
1675 drwxrwxr-x 3 user1 user1 4096 feb 11 16:27 pkg
1676 drwxrwxr-x 8 user1 user1 4096 feb 11 17:05 src
1677 
1678 
1679 $ xadmin provision
1680 Enduro/X 3.4.4, build Feb 11 2017 16:57:21, using epoll for LINUX (64 bits)
1681 
1682 Enduro/X Middleware Platform for Distributed Transaction Processing
1683 Copyright (C) 2015, 2016 Mavimax, Ltd. All Rights Reserved.
1684 
1685 This software is released under one of the following licenses:
1686 GPLv2 (or later) or Mavimax's license for commercial use.
1687 
1688 Logging to ./ULOG.20170212
1689 
1690     ______          __                    ___  __
1691    / ____/___  ____/ /_  ___________    _/_/ |/ /
1692   / __/ / __ \/ __  / / / / ___/ __ \ _/_/ |   / 
1693  / /___/ / / / /_/ / /_/ / /  / /_/ //_/  /   |  
1694 /_____/_/ /_/\__,_/\__,_/_/   \____/_/   /_/|_|  
1695 
1696                      Provision
1697 
1698 Compiled system type....: LINUX
1699 
1700  0: qpath        :Queue device path [/dev/mqueue]: 
1701  1: nodeid       :Cluster node id [1]: 
1702  2: qprefix      :System code (prefix/setfile name, etc) [test1]: app2
1703  3: timeout      :System wide tpcall() timeout, seconds [90]: 
1704  4: appHome      :Application home [$TESTHOME]: 
1705  6: binDir       :Executables/binaries sub-folder of Apphome [bin]: 
1706  8: confDir      :Configuration sub-folder of Apphome [conf]: 
1707  9: logDir       :Log sub-folder of Apphome [log]: 
1708 10: ubfDir       :Unified Buffer Format (UBF) field defs sub-folder of Apphome [ubftab]: 
1709 11: tempDir      :Temp sub-dir (used for pid file) [tmp]: 
1710 12: installQ     :Configure persistent queue [y]: 
1711 13: tmDir        :Transaction Manager Logs sub-folder of Apphome [tmlogs]: 
1712 14: qdata        :Queue data sub-folder of Apphone [qdata]: 
1713 15: qSpace       :Persistent queue space namme [SAMPLESPACE]: 
1714 16: qName        :Sample persistent queue name [TESTQ1]: 
1715 17: qSvc         :Target service for automatic queue for sample Q [TESTSVC1]: 
1716 18: eventSv      :Install event server [y]: 
1717 19: cpmSv        :Configure Client Process Monitor Server [y]: 
1718 20: configSv     :Install Configuration server [y]: 
1719 21: bridge       :Install bridge connection [y]: 
1720 22: bridgeRole   :Bridge -> Role: Active(a) or passive(p)? [a]: 
1721 24: ipc          :Bridge -> IP: Connect to [172.0.0.1]: 
1722 25: port         :Bridge -> IP: Port number [21003]: 
1723 26: otherNodeId  :Other cluster node id [2]: 
1724 27: ipckey       :IPC Key used for System V semaphores [44000]: 
1725 28: ldbal        :Load balance over cluster [0]: 
1726 29: ndrxlev      :Logging: ATMI sub-system log level 5 - highest (debug), 0 - minimum (off) [5]:2 
1727 30: ubflev       :Logging: UBF sub-system log level 5 - highest (debug), 0 - minimum (off) [1]: 
1728 31: tplev        :Logging: /user sub-system log level 5 - highest (debug), 0 - minimum (off) [5]: 
1729 32: usv1         :Configure User server #1 [n]: y
1730 33: usv1_name    :User server #1: binary name []: testsv
1731 34: usv1_min     :User server #1: min [1]: 
1732 35: usv1_max     :User server #1: max [1]: 
1733 36: usv1_srvid   :User server #1: srvid [2000]: 
1734 37: usv1_cctag   :User server #1: cctag []: 
1735 38: usv1_sysopt  :User server #1: sysopt []: 
1736 Invalid value: Min length 1
1737 38: usv1_sysopt  :User server #1: sysopt []: -e ${NDRX_APPHOME}/log/testsv.log
1738 39: usv1_appopt  :User server #1: appopt []: 
1739 50: ucl1         :Configure User client #1 [n]: 
1740 55: addubf       :Additional UBFTAB files (comma seperated), can be empty []: test.fd
1741 56: msgsizemax   :Max IPC message size [56000]: 
1742 57: msgmax       :Max IPC messages in queue [100]: 
1743 
1744 *** Review & edit configuration ***
1745 
1746  0: Edit qpath        :Queue device path [/dev/mqueue]: 
1747  1: Edit nodeid       :Cluster node id [1]: 
1748  2: Edit qprefix      :System code (prefix/setfile name, etc) [app2]: 
1749  3: Edit timeout      :System wide tpcall() timeout, seconds [90]: 
1750  4: Edit appHome      :Application home [$TESTHOME]: 
1751  6: Edit binDir       :Executables/binaries sub-folder of Apphome [bin]: 
1752  8: Edit confDir      :Configuration sub-folder of Apphome [conf]: 
1753  9: Edit logDir       :Log sub-folder of Apphome [log]: 
1754 10: Edit ubfDir       :Unified Buffer Format (UBF) field defs sub-folder of Apphome [ubftab]: 
1755 11: Edit tempDir      :Temp sub-dir (used for pid file) [tmp]: 
1756 12: Edit installQ     :Configure persistent queue [y]: 
1757 13: Edit tmDir        :Transaction Manager Logs sub-folder of Apphome [tmlogs]: 
1758 14: Edit qdata        :Queue data sub-folder of Apphone [qdata]: 
1759 15: Edit qSpace       :Persistent queue space namme [SAMPLESPACE]: 
1760 16: Edit qName        :Sample persistent queue name [TESTQ1]: 
1761 17: Edit qSvc         :Target service for automatic queue for sample Q [TESTSVC1]: 
1762 18: Edit eventSv      :Install event server [y]: 
1763 19: Edit cpmSv        :Configure Client Process Monitor Server [y]: 
1764 20: Edit configSv     :Install Configuration server [y]: 
1765 21: Edit bridge       :Install bridge connection [y]: 
1766 22: Edit bridgeRole   :Bridge -> Role: Active(a) or passive(p)? [a]: 
1767 24: Edit ipc          :Bridge -> IP: Connect to [172.0.0.1]: 
1768 25: Edit port         :Bridge -> IP: Port number [21003]: 
1769 26: Edit otherNodeId  :Other cluster node id [2]: 
1770 27: Edit ipckey       :IPC Key used for System V semaphores [44000]: 
1771 28: Edit ldbal        :Load balance over cluster [0]: 
1772 29: Edit ndrxlev      :Logging: ATMI sub-system log level 5 - highest (debug), 0 - minimum (off) [2]: 
1773 30: Edit ubflev       :Logging: UBF sub-system log level 5 - highest (debug), 0 - minimum (off) [1]: 
1774 31: Edit tplev        :Logging: /user sub-system log level 5 - highest (debug), 0 - minimum (off) [5]: 
1775 32: Edit usv1         :Configure User server #1 [y]: 
1776 33: Edit usv1_name    :User server #1: binary name [testsv]: 
1777 34: Edit usv1_min     :User server #1: min [1]: 
1778 35: Edit usv1_max     :User server #1: max [1]: 
1779 36: Edit usv1_srvid   :User server #1: srvid [2000]: 
1780 37: Edit usv1_cctag   :User server #1: cctag []: 
1781 38: Edit usv1_sysopt  :User server #1: sysopt [-e ${NDRX_APPHOME}/log/testsv.log]: 
1782 39: Edit usv1_appopt  :User server #1: appopt []: 
1783 50: Edit ucl1         :Configure User client #1 [n]: 
1784 55: Edit addubf       :Additional UBFTAB files (comma seperated), can be empty [test.fd]: 
1785 56: Edit msgsizemax   :Max IPC message size [56000]: 
1786 57: Edit msgmax       :Max IPC messages in queue [100]: 
1787 c: Cancel
1788 w: Accept, write
1789 Enter the choice [0-57, c, w]: w
1790 ndrxconfig: [$TESTHOME/conf/ndrxconfig.xml]
1791 appini: [$TESTHOME/conf/app.ini]
1792 setfile: [$TESTHOME/conf/setapp2]
1793 
1794 
1795 To start your system, run following commands:
1796 $ cd $TESTHOME/conf
1797 $ source setapp2
1798 $ xadmin start -y
1799 
1800 
1801 Provision succeed!
1802 
1803 $ ls -l
1804 total 68
1805 drwxrwxr-x 2 user1 user1  4096 feb 12 10:32 bin
1806 drwxrwxr-x 2 user1 user1  4096 feb 12 10:32 conf
1807 drwxrwxr-x 2 user1 user1  4096 feb 12 10:32 log
1808 drwxrwxr-x 3 user1 user1  4096 feb 11 16:27 pkg
1809 drwxrwxr-x 2 user1 user1  4096 feb 12 10:32 qdata
1810 drwxrwxr-x 8 user1 user1  4096 feb 11 17:05 src
1811 drwxrwxr-x 3 user1 user1  4096 feb 12 10:32 tmlogs
1812 drwxrwxr-x 2 user1 user1  4096 feb 12 10:32 tmp
1813 drwxrwxr-x 2 user1 user1  4096 feb 12 10:32 ubftab
1814 -rw-rw-r-- 1 user1 user1 30755 feb 12 10:32 ULOG.20170212
1815 
1816 --------------------------------------------------------------------------------
1817 
1818 Once the system is provisioned, we need to put the symbolic links to our binaries
1819 to Enduro/X runtime "bin" directory. Also we will put our test field definition
1820 file *test.fd* into *$TESTHOME/ubftab* folder.
1821 
1822 --------------------------------------------------------------------------------
1823 
1824 $ cd $TESTHOME/bin
1825 
1826 $ ln -s $TESTHOME/src/clt/testcl .
1827 
1828 $ ln -s $TESTHOME/src/srv/testsv .
1829 
1830 $ cd $TESTHOME/ubftab
1831 
1832 $ ln -s $TESTHOME/src/ubftab/test.fd .
1833 
1834 --------------------------------------------------------------------------------
1835 
1836 Now we are ready to boot up the runtime:
1837 
1838 --------------------------------------------------------------------------------
1839 $ cd $TESTHOME/conf
1840 $ source setapp2
1841 $ xadmin start -y
1842 Enduro/X 3.4.4, build Feb 11 2017 16:57:21, using epoll for LINUX (64 bits)
1843 
1844 Enduro/X Middleware Platform for Distributed Transaction Processing
1845 Copyright (C) 2015, 2016 Mavimax, Ltd. All Rights Reserved.
1846 
1847 This software is released under one of the following licenses:
1848 GPLv2 (or later) or Mavimax's license for commercial use.
1849 
1850 EnduroX back-end (ndrxd) is not running
1851 ndrxd PID (from PID file): 18849
1852 ndrxd idle instance started.
1853 exec cconfsrv -k 0myWI5nu -i 1 -e $TESTHOME/log/cconfsrv.log -r --  :
1854         process id=18851 ... Started.
1855 exec cconfsrv -k 0myWI5nu -i 2 -e $TESTHOME/log/cconfsrv.log -r --  :
1856         process id=18852 ... Started.
1857 exec tpevsrv -k 0myWI5nu -i 20 -e $TESTHOME/log/tpevsrv.log -r --  :
1858         process id=18853 ... Started.
1859 exec tpevsrv -k 0myWI5nu -i 21 -e $TESTHOME/log/tpevsrv.log -r --  :
1860         process id=18854 ... Started.
1861 exec tmsrv -k 0myWI5nu -i 40 -e $TESTHOME/log/tmsrv-rm1.log -r -- -t1 -l$TESTHOME/tmlogs/rm1 --  :
1862         process id=18855 ... Started.
1863 exec tmsrv -k 0myWI5nu -i 41 -e $TESTHOME/log/tmsrv-rm1.log -r -- -t1 -l$TESTHOME/tmlogs/rm1 --  :
1864         process id=18867 ... Started.
1865 exec tmsrv -k 0myWI5nu -i 42 -e $TESTHOME/log/tmsrv-rm1.log -r -- -t1 -l$TESTHOME/tmlogs/rm1 --  :
1866         process id=18879 ... Started.
1867 exec tmqueue -k 0myWI5nu -i 60 -e $TESTHOME/log/tmqueue-rm1.log -r -- -m SAMPLESPACE -s1 --  :
1868         process id=18891 ... Started.
1869 exec tpbridge -k 0myWI5nu -i 150 -e $TESTHOME/log/tpbridge_2.log -r -- -f -n2 -r -i 172.0.0.1 -p 21003 -tA -z30 :
1870         process id=18923 ... Started.
1871 exec testsv -k 0myWI5nu -i 2000 -e $TESTHOME/log/testsv.log --  :
1872         process id=18924 ... Started.
1873 exec cpmsrv -k 0myWI5nu -i 9999 -e $TESTHOME/log/cpmsrv.log -r -- -k3 -i1 --  :
1874         process id=18929 ... Started.
1875 Startup finished. 11 processes started.
1876 --------------------------------------------------------------------------------
1877 
1878 
1879 Now test availability of our test service:
1880 --------------------------------------------------------------------------------
1881 $ xadmin psc
1882 Enduro/X 3.4.4, build Feb 11 2017 16:57:21, using epoll for LINUX (64 bits)
1883 
1884 Enduro/X Middleware Platform for Distributed Transaction Processing
1885 Copyright (C) 2015, 2016 Mavimax, Ltd. All Rights Reserved.
1886 
1887 This software is released under one of the following licenses:
1888 GPLv2 (or later) or Mavimax's license for commercial use.
1889 
1890 ndrxd PID (from PID file): 6119
1891 Nd Service Name Routine Name Prog Name SRVID #SUCC #FAIL MAX      LAST     STAT
1892 -- ------------ ------------ --------- ----- ----- ----- -------- -------- -----
1893 1  @CCONF       CCONF        cconfsrv  1     0     0     0ms      0ms      AVAIL
1894 1  @CCONF       CCONF        cconfsrv  2     0     0     0ms      0ms      AVAIL
1895 1  @TPEVSUBS    TPEVSUBS     tpevsrv   20    0     0     0ms      0ms      AVAIL
1896 1  @TPEVUNSUBS  TPEVUNSUBS   tpevsrv   20    0     0     0ms      0ms      AVAIL
1897 1  @TPEVPOST    TPEVPOST     tpevsrv   20    0     0     0ms      0ms      AVAIL
1898 1  @TPEVDOPOST  TPEVDOPOST   tpevsrv   20    0     0     0ms      0ms      AVAIL
1899 1  @TPEVSUBS    TPEVSUBS     tpevsrv   21    0     0     0ms      0ms      AVAIL
1900 1  @TPEVUNSUBS  TPEVUNSUBS   tpevsrv   21    0     0     0ms      0ms      AVAIL
1901 1  @TPEVPOST    TPEVPOST     tpevsrv   21    0     0     0ms      0ms      AVAIL
1902 1  @TPEVDOPOST  TPEVDOPOST   tpevsrv   21    0     0     0ms      0ms      AVAIL
1903 1  @TM-1        TPTMSRV      tmsrv     40    0     0     0ms      0ms      AVAIL
1904 1  @TM-1-1      TPTMSRV      tmsrv     40    0     0     0ms      0ms      AVAIL
1905 1  @TM-1-1-40   TPTMSRV      tmsrv     40    0     0     0ms      0ms      AVAIL
1906 1  @TM-1        TPTMSRV      tmsrv     41    0     0     0ms      0ms      AVAIL
1907 1  @TM-1-1      TPTMSRV      tmsrv     41    0     0     0ms      0ms      AVAIL
1908 1  @TM-1-1-41   TPTMSRV      tmsrv     41    0     0     0ms      0ms      AVAIL
1909 1  @TM-1        TPTMSRV      tmsrv     42    0     0     0ms      0ms      AVAIL
1910 1  @TM-1-1      TPTMSRV      tmsrv     42    0     0     0ms      0ms      AVAIL
1911 1  @TM-1-1-42   TPTMSRV      tmsrv     42    0     0     0ms      0ms      AVAIL
1912 1  @TMQ-1-60    TMQUEUE      tmqueue   60    0     0     0ms      0ms      AVAIL
1913 1  @QSPSAMPLES+ TMQUEUE      tmqueue   60    0     0     0ms      0ms      AVAIL
1914 1  @TPBRIDGE002 TPBRIDGE     tpbridge  150   0     0     0ms      0ms      AVAIL
1915 1  TESTSV       TESTSV       testsv    2000  0     0     0ms      0ms      AVAIL
1916 1  @CPMSVC      CPMSVC       cpmsrv    9999  0     0     0ms      0ms      AVAIL
1917 --------------------------------------------------------------------------------
1918 
1919 *TESTSV* is advertised, thus all is ok. No try will run the test client.
1920 
1921 ==== Run the client
1922 
1923 We will run the client by simply invoking in shell *testcl* binary. The working
1924 progress will be logged on output.
1925 --------------------------------------------------------------------------------
1926 $ testcl 
1927 t:USER:4: 6845:7fd1d85b47c0:000:20170212:191211999:testcl.c:0044:Initializing...
1928 t:USER:4: 6845:7fd1d85b47c0:000:20170212:191212000:testcl.c:0090:Processing...
1929 T_STRING_FLD    Hello world!
1930 T_STRING_2_FLD  Hello World from XATMI server
1931 t:USER:4: 6845:7fd1d85b47c0:000:20170212:191212004:testcl.c:0129:Got response from server: [Hello World from XATMI server]
1932 t:USER:4: 6845:7fd1d85b47c0:000:20170212:191212004:testcl.c:0069:Uninitializing...
1933 --------------------------------------------------------------------------------
1934 
1935 Thus as we see from the sample run it did call the server and got back the response
1936 "Hello World from XATMI server". Thus we can conclude that server and client was
1937 successfully generated and runtime provisioned.
1938 
1939 
1940 == Using unsolicited messages
1941 
1942 Enduro/X supports unsolicited messages. The idea is that server
1943 process (or other client processes which have a handler to client) 
1944 can send unsolicited messages to clients. The client processes consumes these
1945 messages and invokes the callback function. The callback is invoked in case if
1946 callback handler is set by *tpsetunsol(3)* function.
1947 
1948 The unsolicited messages are posted by XATMI services by using *tpnotify(3)*. This
1949 function gets the Client ID (extracted from service call parameter structure, 
1950 field TPSVCINFO.cltid:
1951 
1952 --------------------------------------------------------------------------------
1953 
1954 void SOMESERVICE (TPSVCINFO *p_svc)
1955 {
1956     ...
1957     if (0!=tpnotify(&p_svc->cltid, (char *)p_ub, 0L, 0L))
1958     {
1959         NDRX_LOG(log_error, "Failed to tpnotify()!");
1960         ...
1961     }
1962     ...
1963 
1964 }
1965 
1966 --------------------------------------------------------------------------------
1967 
1968 Unsolicited messages can be broadcast to client processes by servers and client
1969 by using *tpbroadcast(3)*. The broadcast takes Enduro/X cluster node id 
1970 ('lmid' param) and client name ('cltname' param). The match of the client processes
1971 are made by either field present (exact match), field not present (match all) or
1972 match by regular expression.
1973 
1974 Function signatures are following:
1975 
1976 --------------------------------------------------------------------------------
1977 
1978 int tpnotify(CLIENTID *clientid, char *data, long len, long flags);
1979 int tpbroadcast(char *lmid, char *usrname, char *cltname, char *data, long len, long flags);
1980 
1981 --------------------------------------------------------------------------------
1982 
1983 
1984 === Unsolicited message callback processing
1985 
1986 The callback function receives XATMI buffer which was provided to the *tpnotify(3)*
1987 or *tpbroadcast(3)*. When callback processes these messages, there is limited availability
1988 of the operations that can be performed within the callback. The limitation is
1989 due to fact, that unsolicited messages are provided from internals of the XATMI
1990 runtime and for example doing *tpcall(3)* might cause recursive invocation of
1991 the callback handler and can cause stack overflow. The following list of XATMI
1992 functions are available during the callback processing:
1993 
1994 . *tpalloc(3)*
1995 
1996 . *tpfree(3)*
1997 
1998 . *tpgetlev(3)*
1999 
2000 . *tprealloc(3)*
2001 
2002 . *tptypes(3)*
2003 
2004 If more advanced processing is required, the user might create a new thread, copy
2005 the XATMI buffer and pass it to the thread. Copy of the buffer is required due to
2006 fact, that buffer is automatic made free when callback function returns.
2007 
2008 === Networked operations
2009 
2010 When sending the message to the client to different Enduro/X cluster node, then
2011 the transport of the notification is performed by *tpbridge(8)* bridge process,
2012 but remote dispatching is performed by special XATMI server named *tpbrdcstsv(8)*.
2013 To overall notifications are processed in this way:
2014 
2015 
2016 [dia, tpnotify.dia, tpnotify.png, x450]
2017 -------------------------------
2018 -------------------------------
2019 
2020 the picture contains:
2021 
2022 . Local tpnotify() - orange color
2023 
2024 . Local and remote tpbroadcast() - gray color
2025 
2026 . Remote tpnotify() - green
2027 
2028 === Unsolicited message applications
2029 
2030 Unsolicited messages can be used for XATMI service reporting back progress of some
2031 particular work the client. Thus the *tpcall(3)* is not interrupted, but some
2032 feedback can be received and processed.
2033 
2034 Sample usage can be seen in Enduro/X ATMI test cases 38 and 39.
2035 
2036 == Adding Enduro/X bindings
2037 
2038 Currently Enduro/X have tier 1 bindings for th Go language. This implementation
2039 can be used as reference for other language implementations. The core for the binding
2040 development is following:
2041 
2042 We classically start with "data structures and algorithms"! Thust firstly define a
2043 structures.
2044 
2045 But before we start the development, we need to create a build system for target
2046 language. The package name is endurox-<language name>, .e.g endurox-java. The 
2047 build system shall build the corresponding library and test executables.
2048 
2049 1. Add enumeration of Enduro/X constants
2050 
2051 2. Define error object, either it is just struct or exception classes
2052 
2053 3. Create ATMI Context struct/class
2054 
2055 4. Define Generic ATMI Buffer Object, add inherited objects to STRING, UBF, JSON, RAW/CARRAY
2056 
2057 5. Advertise service (this means from high level language call Ondrx_main(), 
2058 which will make init callback). Needs to advertise service and allow the ndrx_main() 
2059 to start to poll for messages. Once the message arrives we need to callback a 
2060 language specific function.
2061 
2062 The bindings will use all libs server & client (like a Go). Thus it depends 
2063 on the application logic either the binary becomes server or it will be just a client.
2064 
2065 == Plugin interface
2066 
2067 Enduro/X provides API for writing custom plugins (loaded by shared libraries).
2068 There are certain criteria to which plugins must correspond. This chapter will
2069 provide the plugin API definition. Also it will list the functionality which
2070 can be defined by plugin. Plugins shall be written in thread safe manner.
2071 
2072 Plugin interface if provided via *expluginbase.h* header.
2073 
2074 === Plugin Initialization
2075 
2076 Plugins are registered in 'NDRX_PLUGINS' environment variable, as semicolon separated
2077 values. Plugins are loaded during the process "boostarp" (basically at the time
2078 when Enduro/X debug logger is initialized, before the Common-Configuration is
2079 read. Thus plugins cannot be registered in '[@global]' section. As they must
2080 be already loaded before the INI file parsing, as for example custom cryptography
2081 provider might be used. Libraries must be available in current shared library
2082 search path (e.g. LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, etc..).
2083 
2084 Sample configuration:
2085 
2086 --------------------------------------------------------------------------------
2087 
2088 $ export NDRX_PLUGINS=customcrypto.so;somotherfunc.so
2089 
2090 --------------------------------------------------------------------------------
2091 
2092 Enduro/X plugin interface requires two *mandatory* symbols to be exported from
2093 plugin library, which must correspond to the following signature:
2094 
2095 --------------------------------------------------------------------------------
2096 
2097 long ndrx_plugin_init(char *provider_name, int provider_name_bufsz);
2098 
2099 --------------------------------------------------------------------------------
2100 
2101 Where 'provider_name' is arbitrary string describing the plugin. 'provider_name_bufsz'
2102 is buffer size for the plugin description. Typically it is around ~60 bytes.
2103 
2104 In case of error function shall return *-1*. In case of success init function
2105 shall return one or more NDRX_PLUGIN_FUNC_XXXX OR'ed bits, denoting the
2106 functionality which is being exported.
2107 
2108 Currently following flags are available:
2109 
2110 . NDRX_PLUGIN_FUNC_ENCKEY (0x00000001) - plugin provides cryptography key function
2111 
2112 . NDRX_PLUGIN_FUNC_TPLOGPRINTUBF_HOOK (0x00000002) - hook for tplogprintubf() func
2113 
2114 
2115 During the Initialization, only early logging (mem buffered logs) are available,
2116 see NDRX_LOG_EARLY/UBF_LOG_EARLY/TP_LOG_EARLY. If use of other log functions is
2117 made, then must probably program will deadlock.
2118 
2119 
2120 === NDRX_PLUGIN_FUNC_ENCKEY functions
2121 
2122 If plugin exports this flag, then library loader will search for following
2123 symbol in the shared library:
2124 
2125 --------------------------------------------------------------------------------
2126 
2127 int ndrx_plugin_crypto_getkey(char *keybuf, int keybuf_bufsz);
2128 
2129 --------------------------------------------------------------------------------
2130 
2131 Where 'keybuf' is buffer where to install encryption key. The encryption key
2132 must be zero (0x00) terminated C string. 'keybuf_bufsz' denotes the max buffer
2133 size (with 0x00 byte). In case of success function shall return 0. In case of 
2134 failure, function shall return -1. For this function only *EARLY* logging is
2135 available (NDRX_LOG_EARLY/UBF_LOG_EARLY/TP_LOG_EARLY).
2136 
2137 
2138 === NDRX_PLUGIN_FUNC_TPLOGPRINTUBF_HOOK functions
2139 
2140 If plugin exports this flag, then library loader will search for following
2141 symbol in the shared library:
2142 
2143 --------------------------------------------------------------------------------
2144 
2145 int ndrx_plugin_tplogprintubf_hook(char **buffer, long datalen, void *dataptr1, 
2146         int *do_write, FILE * outf, int fid);
2147 
2148 --------------------------------------------------------------------------------
2149 
2150 Function is used to catch the moment when *tplogprintubf(3)* prints the UBF buffer
2151 in log file, line by line. For every line the function is called. The 'buffer'
2152 receives the pointer to dynamically allocated string where current output data
2153 is formatted. The format of the line is following "<field_name>\t<any_data>\n".
2154 Total buffer length is passed in 'datalen' field. 'dataptr1' is reserved for
2155 future use. 'do_write' by default is set to FALSE - *0*, if set to TRUE *1*, the
2156 line will be logged to the logging device. 'outf' is current output stream.
2157 'fid' is UBF buffer field id currently being printed out.
2158 
2159 The plugin function can capture the output, or it can replace the data in 'buffer',
2160 user is allowed to reallocate the 'buffer'. Enduro/X does free() call on the
2161 'buffer' after the invocation.
2162 
2163 See atmitest/test070_ubfhook/hookplugin.c for sample code.
2164 
2165 
2166 == Starting Enduro/X XATMI server from other thread than main
2167 
2168 For some scenarios it might be needed to create XATMI server to which main thread
2169 is busy with some other functionality. And only auxiliary thread may perform XATMI
2170 servicing actions. All this can be simply done with help of "libatmisrvinteg" and
2171 ndrx_main_integra() function. Thus following code fragment creates a simple server
2172 and provides command to build it under GNU/Linux.
2173 
2174 --------------------------------------------------------------------------------
2175 
2176 #include <string.h>
2177 #include <stdio.h>
2178 #include <stdlib.h>
2179 #include <memory.h>
2180 #include <math.h>
2181 
2182 #include <unistd.h>
2183 #include <sys/types.h>
2184 #include <errno.h>
2185 #include <stdio.h>
2186 #include <stdlib.h>
2187 #include <pthread.h>
2188 
2189 #include <atmi.h>
2190 #include <ubf.h>
2191 #include <ndebug.h>
2192 #include <unistd.h>
2193 
2194 
2195 int M_argc;
2196 char **M_argv;
2197 
2198 
2199 /**
2200  * Service does not return anything...
2201  */
2202 void HELLOSVC (TPSVCINFO *p_svc)
2203 {
2204    tpreturn (TPSUCCESS, 0L, NULL, 0L, 0L);
2205 }
2206 
2207 
2208 /**
2209  * XATMI init callback
2210  */
2211 int tpsvrinit(int argc, char **argv)
2212 {
2213     NDRX_LOG(log_debug, "tpsvrinit called");
2214 
2215     if (EXSUCCEED!=tpadvertise("HELLOSVC", HELLOSVC))
2216     {
2217         NDRX_LOG(log_error, "Failed to initialize HELLOSVC!");
2218         return -1;
2219     }
2220 
2221     return 0;
2222 }
2223 
2224 /**
2225  * Do de-initialization
2226  */
2227 void tpsvrdone(void)
2228 {
2229     NDRX_LOG(log_debug, "tpsvrdone called");
2230 }
2231 
2232 /**
2233  * Run run_xatmi_server from thread
2234  */
2235 void run_xatmi_server ( void *ptr )
2236 {
2237     if (0!=ndrx_main_integra(M_argc, M_argv, 
2238         /* set callbacks: */
2239         tpsvrinit, tpsvrdone, 
2240         0L))
2241     {
2242         NDRX_LOG(log_error, "Failed to run Enduro/X main: %s", 
2243         tpstrerror(tperrno));
2244         exit(1);
2245     }
2246 }
2247 
2248 
2249 /**
2250  * Standard main entry...
2251  */
2252 int main(int argc, char** argv) 
2253 {
2254 
2255     pthread_t thread1;
2256     pthread_attr_t pthread_custom_attr;
2257 
2258     M_argc = argc;
2259     M_argv = argv;
2260 
2261     pthread_attr_init(&pthread_custom_attr);
2262 
2263     /* Configure stack, using Enduro/X internal method...
2264      * but you can configure it by your self.
2265      */
2266     pthread_attr_setstacksize(&pthread_custom_attr, 
2267             ndrx_platf_stack_get_size());
2268      
2269     pthread_create (&thread1, &pthread_custom_attr, (void *) &run_xatmi_server, NULL);
2270 
2271 
2272     pthread_join(thread1, NULL);
2273 
2274 
2275     return 0;
2276 }
2277 
2278 --------------------------------------------------------------------------------
2279 
2280 To compile the code, you may just use C compiler:
2281 
2282 --------------------------------------------------------------------------------
2283 
2284 $ cc -o samplesv  sample.c -latmisrvinteg -latmi -lubf -lnstd -lpthread -lrt -ldl -lm
2285 
2286 --------------------------------------------------------------------------------
2287 
2288 To boot the server, you may add it to ndrxconfig.xml and boot it up:
2289 
2290 
2291 --------------------------------------------------------------------------------
2292 ...
2293         <servers>
2294 ...
2295                 <server name="samplesv">
2296                         <srvid>1600</srvid>
2297                         <min>1</min>
2298                         <max>1</max>
2299                         <sysopt>-e /tmp/SAMPLE_1 -r</sysopt>
2300                 </server>
2301 ...
2302         </servers>
2303 ...
2304 --------------------------------------------------------------------------------
2305 
2306 
2307 Finally give it a test:
2308 
2309 --------------------------------------------------------------------------------
2310 
2311 NDRX> start -y
2312 ...
2313 exec samplesv -k 0myWI5nu -i 1600 -e /tmp/SAMPLE_1 -r --  :
2314         process id=9650 ... Started.
2315 ...
2316 
2317 NDRX> psc
2318 Nd Service Name Routine Name Prog Name SRVID #SUCC #FAIL MAX      LAST     STAT
2319 -- ------------ ------------ --------- ----- ----- ----- -------- -------- -----
2320 ...
2321 1  HELLOSVC     HELLOSVC     samplesv  1600  0     0     0ms      0ms      AVAIL
2322 ...
2323 NDRX> 
2324 
2325 --------------------------------------------------------------------------------
2326 
2327 *NOTE*: the process is started with standard command line with args like -k/-i/-e
2328 and '--'. If your existing software also uses CLI arguments, then it must be modified
2329 so that it does not crash with unknown keys. Also Enduro/X XATMI server will not
2330 tolerate any other third party keys. Those other keys user might add it "appopts"
2331 section, followed by "--". See ndrxconfig.xml(5) for more details.
2332 
2333 === Enduro/X Process naming strategies
2334 
2335 The process naming strategies are complex ones, due to fact that server processes
2336 can be booted for shell-scripts and Enduro/X sees the upper level script name
2337 and not the actual binary which performs the XATMI work. The process name
2338 participates in following functional areas:
2339 
2340 . For clients, is opening of client's reply queue
2341 
2342 . For servers, it is used for admin queues and reply queues.
2343 
2344 The *ndrxd* daemon performs sanity checks, and it is doing cross-validation,
2345 that server queue with process name X and PID Y exists in system. While for queue
2346 cross validation, all is ok, as X and Y exists, the problem is with cases when
2347 *ndrxd* performs server PINGs. To build admin queue name to send ping to, *ndrxd*
2348 uses the binary name it knows (either server name or real name extracted from
2349 command line). As command line can contain shell script, *ndrxd* will not be
2350 able to send PINGs to server process, as queue will be different, and then *ndrxd*
2351 will kill the process as not pingable.
2352 
2353 
2354 ==== Strategy 1
2355 
2356 To cope with above cases, Enduro/X uses following solution:
2357 
2358 . If NDRX_SVPROCNAME is exported, then server process opens queue with this name.
2359 
2360 . In normal case NDRX_SVPROCNAME matches the server binary name, thus no changes
2361 for existing system logic.
2362 
2363 . In case of Java env, the 'argv[0]' will be set to this environment variable
2364 or it will use just keyword "java" if variable is not available.
2365 
2366 
2367 To check that process exists, for servers this could be done in this way:
2368 
2369 . Check the PID existence (extracted from Q name)
2370 
2371 . Check the Process name existence (extracted from Q), does it match the PID
2372 (exec in the same approach of first test)
2373 
2374 . If does not exists, lookup the Process Model (PM). If the extracted name matches
2375 process name in PM, and the name from CLI matches the real name, the process exists.
2376 
2377 . If above does not work out, lookup the environment variables of the process,
2378 check the existence of NDRX_SVPROCNAME variable. If value matches the name extracted
2379 from queue, then process is alive.
2380 
2381 . Otherwise process is dead. 
2382 
2383 
2384 ==== Strategy 2
2385 
2386 The server process reports the final process name to the *ndrxd* while it reports
2387 it's status and advertised services. At this point *ndrxd* may start to send pings
2388 to server. Regarding of pinging non reported servers, this is up to *ndrxd* current
2389 algorithms of when to ping.
2390 
2391 Initially we take server name or exe name from command line as one to which admin
2392 messages shall be sent (prior receiving the name from the process).
2393 
2394 
2395 The Strategy 2 is simpler to implement. The Strategy 1 shows the server queues
2396 as virtual process names. That might be simpler for admins to understand
2397 to whom the queue belongs to.
2398 
2399 
2400 === Booting processes as XATMI servers without CLOPT
2401 
2402 There could be server processes like Tomcat or JBoss App servers which we might
2403 want to boot as XATMI servers. For these command line options cannot be passed
2404 in. Thus at ps -ef the output will not show Enduro/X specific flags like -k (
2405 unique app key), -i (server instance id), -e (error log), etc.
2406 
2407 One approach would be to pass these command line options in NDRX_SVCLOPT variable.
2408 But again we will have an issue with some functional areas - like "xadmin down"
2409 command.
2410 
2411 This could be solved by doing peek into other process environment. If we find
2412 the unique string there - then server process is subject for killing.
2413 
2414 
2415 == Process forking
2416 
2417 There are special moments to take care of when Enduro/X process either XATMI
2418 client or XATMI server want's to perform forking (i.e. duplicate process).
2419 
2420 Enduro/X offers following APIs to support better forking flow:
2421 
2422 . *ndrx_fork(3)* which is wrapper for *fork()* call which includes any
2423 resource deallocations/allocations necessary.
2424 
2425 . Another way if stock *fork()* needs to be used, then Enduro/X supports 
2426 following APIs: *ndrx_atfork_prepare()* - parent calls before fork, 
2427 *ndrx_atfork_parent()* - parent calls after fork, *ndrx_atfork_child()* -
2428 child calls after fork. 
2429  
2430 There are three kind of issues that needs to be solved when forking. 
2431 
2432 1. In case of XATMI server process, when child process is forked, 
2433 any server queues must be closed to avoid memory leaks. This can be solved by
2434 either using *ndrx_fork(3)* or by calling *ndrx_atfork_child()*.
2435 
2436 2. If client process (or server process with threaded clients) is forked,
2437 then clients must be freed by *tpterm(3)* manually by developer.
2438 
2439 3. In case if System V queues are used, auxiliary threads must be terminated,
2440 resources released and auxiliary threads must be resumed for parent process. This
2441 can be solved either by using *ndrx_fork(3)*, or 
2442 *ndrx_atfork_prepare()*/*ndrx_atfork_parent()*/*ndrx_atfork_child()*.
2443 
2444 Functions *ndrx_atfork_prepare()*/*ndrx_atfork_parent()*/*ndrx_atfork_child()*
2445 can be registered with *pthread_fork()* so that library fork calls are supported.
2446 
2447 *WARNING!* When operating in System V mode and user is performing *ndrx_fork(3)*,
2448 any other user threads shall not perform XATMI IPCs (tpcalls, tprecv, etc..) 
2449 in any other concurrent user thread, otherwise unexpected process corruption
2450 might happen. Thus corresponding synchronization shall be done at user code.
2451 
2452 == Source code management
2453 
2454 This section lists notes for Git usage for Enduro/X development. Usually we
2455 modify the sample configuration in directory *sampleconfig* in order to get the
2456 test system working. But these changes should not be committed, as mostly
2457 they are local means and local config. Thus to avoid the changed files from
2458 auto commit when using *git commit -a*, files can be marked as "unchanged"
2459 by following git command:
2460 
2461 --------------------------------------------------------------------------------
2462 
2463 $ git update-index --assume-unchanged sampleconfig/debug.conf
2464 $ git update-index --assume-unchanged sampleconfig/ndrxconfig.xml
2465 $ git update-index --assume-unchanged sampleconfig/setndrx
2466 
2467 --------------------------------------------------------------------------------
2468 
2469 
2470 == Process debugging
2471 
2472 This section lists some notes about techniques for debugging memory issues for
2473 the binaries.
2474 
2475 
2476 === Tracking down memory usage with Valgrind for XATMI servers
2477 
2478 Valgrind utility can be used with XATMI servers to get some insight in memory
2479 usage and leaks. Here is the sample XATMI server definition which uses Valgrind
2480 wrapper for server boot.
2481 
2482 --------------------------------------------------------------------------------
2483  <server name="myserver">
2484       <srvid>100</srvid>
2485       <min>1</min>
2486       <max>1</max>
2487       <sysopt>-e /tmp/MYSERVER -r</sysopt>
2488       <appopt>-c10</appopt>
2489       <cmdline>valgrind --leak-check=yes --log-file=/tmp/valg.log ${NDRX_SVPROCNAME} ${NDRX_SVCLOPT}</cmdline>
2490  </server>
2491 --------------------------------------------------------------------------------
2492 
2493 
2494 == Two Phase Commit Processing notes
2495 
2496 This section describes various aspects of distributed transaction processing.
2497 
2498 === Normal Enduro/X Operations of Two Phase Commit
2499 
2500 The processing sequence of distributed transaction from XATMI point of view
2501 is following:
2502 
2503 - For each Resource Manager (RM, e.g. database), there is configured *tmsrv(8)*
2504 process.
2505 
2506 - XATMI process connects to RM with *tpopen(3)* function call
2507 
2508 - XATMI process starts transaction with *tpbegin(3)* function call. When this
2509 request is issued, internally this calls *tmsrv(8)* for requesting the new
2510 transaction XID. At this point tmsrv start accounting of the transaction. And
2511 XID is returned to the caller process.
2512 
2513 - XATMI process calls starts transaction by call of xa_start(). Previous versions
2514 of Enduro/X used *TMJOIN* flag, because tmsrv did already start the transaction in
2515 database. With 6.1 release, TMJOIN is not used, because tmsrv only generates XID,
2516 and does not perform any work with database.
2517 
2518 - In case of process doing tpsuspend(3) call, the xa_end() function with 
2519 *TMSUCCESS* is called. The suspend data can be used by other processes on
2520 the same architecture machines to resume the transaction.
2521 
2522 
2523 === Non XA Switch ready database
2524 
2525 There are several databases which provide incomplete support for X/Open Groups
2526 XA Standard implementation. For example Mysql/MariaDB or Postgresql. In case
2527 of these databases, process cannot join existing transaction with xa_start().
2528 Thus here every time process attempts to join TX, new transaction id is
2529 requested from master *tmsrv*. The *tmsrv* logs this id in journal file,
2530 because even if transaction is not prepared, for Postgresql prepare is only
2531 way to report the XID to database.
2532 
2533 === TMSRV Transaction log format
2534 
2535 Currently there are to versions of the log, v1 and v1.1. V1.1 version is extended
2536 for Multi TID per RM support. Transaction log file consists of several record
2537 types. It logs general info about transaction, information about current 
2538 state and each Resource Managers (RM) status. The file format is simple. It is
2539 text file with Unix newlines. Each record is written on each text line. The
2540 field separator in record is colon ":". Each record starts with Unix UTC
2541 timestamp in milliseconds. Each line is terminated semicolon (";") following 
2542 the CRC32 checksum as 8 hex digits. Checksum is calculate from previous line data.
2543 Checksum is used in crash recovery to identify bad records.
2544 
2545 Log handling is done in *tmsrv/log.c*
2546 source code. Following record types ("log commands") are used:
2547 
2548 - *I* - General Information about transaction, version V1 record.
2549 
2550 - *J* - General Information about transaction, version V2 record.
2551 
2552 - *S* - Identify stage of transaction (is it active, committing, abort, etc.)
2553 
2554 - *R* - Resource manager status information (is it active, prepared, committed, etc.)
2555 
2556 ==== General info about the transaction
2557 
2558 This gives basically some initial infos about transaction. Which tmsrv created
2559 it, what is the timeout setting.
2560 
2561 
2562 [width="80%", options="header"]
2563 |=========================================================
2564 |Nr|Field name|Type|Mand/Opt|Version|Description
2565 |1|tstamp|N13|Mand|1|UTC Time stamp when record added
2566 |2|cmdid|Const "I"|C1|1|Record type identifier, version 1.
2567 |2|cmdid|Const "J"|C1|2|Record type identifier, version 2.
2568 |3|tmrmid|N..5|Mand|1|Resource manager ID which have started TX
2569 |4|tmnodeid|N..5|Mand|1|Cluster Node id which started transaction
2570 |5|tmsrvid|N..5|Mand|1|Transaction manager server id (srvid from ndrxconfig.xml)
2571 |6|txtout|N..19|Mand|1|Transaction timeout set by tpbegin(3)
2572 |7|rmsbuf|ANS..1023|Mand|In version 1 this
2573 was list of active resource managers. Starting with Enduro/X 6.1, transaction logging is start when
2574 transaction is active, thus each active RM is logged with *R* record. Thus there is
2575 no real reason for this record. Thus from Enduro/X 6.1 this fields is not used.
2576 |=========================================================
2577 
2578 *C1* - One of the fields must be present, but not both.
2579 
2580 ==== Transaction stage identification
2581 
2582 [width="80%", options="header"]
2583 |=========================================================
2584 |Nr|Field name|Type|Mand/Opt|Version|Description
2585 |1|tstamp|N13|Mand|1|UTC Time stamp when record added
2586 |2|cmdid|Const "S"|Mand|1|Record type identifier
2587 |3|txstage|N..2|Mand|1|*0* - transaction does no exists,
2588 *5* - transaction is active in processing,
2589 *20* - transaction is aborting,
2590 *25* - transaction aborted with hazard (no xa_forget call),
2591 *30* - heuristically aborted (no xa_forget call),
2592 *35* - aborted ok,
2593 *36* - aborted/xa_forget finishing in progress,
2594 *37* - aborted/hazard finished (xa_forget ok),
2595 *38* - aborted/heuristic finished (xa_forget ok),
2596 *40* - preparing,
2597 *41* - preparing (no participants),
2598 *55* - committed (hazard),
2599 *65* - heuristically committed,
2600 *70* - committed ok,
2601 *80* - committed/xa_forget finishing in progress,
2602 *85* - committed/hazard finished (xa_forget ok),
2603 *87* - committed/heuristic finished (xa_forget ok)
2604 |=========================================================
2605 
2606 
2607 ==== Resource manager status information
2608 
2609 Each resource manager (database, etc) has it's own status distributed transaction,
2610 either it is joined to transaction, prepared, committed, error. If resource
2611 manager supports *TMJOIN*, then only one record is made for resource manager.
2612 If resource manager does not support *TMJOIN*, then each time thread starts to
2613 process, new transaction id is requested. Thus it is logged separately to log file.
2614 This functionality is starting with record version 2.
2615 
2616 [width="80%", options="header"]
2617 |=========================================================
2618 |Nr|Field name|Type|Mand/Opt|Version|Description
2619 |1|tstamp|N13|Mand|1|UTC Time stamp when record added
2620 |2|cmdid|Const "R"|Mand|1|Record type identifier - resource manager status
2621 |3|rmid|N..5|Mand|1|Particular ID of resource manager for which
2622 status is being tracked
2623 |4|rmstatus|A1|Mand|1|0x0 - NULL, 
2624 *n* - Non transaction,
2625 *i* - Idle state (not used),
2626 *j* - RM is in joined state (active),
2627 *p* - RM is in prepared state,
2628 *a* - RM is in abort state,
2629 *b* - Aborted (heuristically),
2630 *d* - Aborted (hazard),
2631 *c*- Committed,
2632 *r* - Committed (was read only),
2633 *h* - Committed (Heuristically),
2634 *z* - Hazard (committed or aborted),
2635 *e* - Aborted/hazard xa_forget() call required,
2636 *f* - Aborted/heuristic xa_forget() call required,
2637 *g* - Committed/hazard xa_forget() call required,
2638 *l* - Committed/heuristic xa_forget() call required,
2639 |5|rmerrorcode|N..3|Mand|1|TP Error code when RM entered in this status. *0* -
2640 means no error occurred.
2641 |6|rmreason|NS..4|Mand|1|XA Error code for caused RM status.
2642 |7|btid|N..19|Opt|2|Transaction id, per resource manager. If value
2643 is not set, then it defaults to *0*
2644 |=========================================================
2645 
2646 
2647 numbered!:
2648 
2649 [bibliography]
2650 Additional documentation 
2651 ------------------------
2652 This section lists additional related documents.
2653 
2654 [bibliography]
2655 .Internet resources
2656 
2657 - *N/A*
2658 
2659 [glossary]
2660 Glossary
2661 --------
2662 This section lists
2663 
2664 [glossary]
2665 ATMI::
2666   Application Transaction Monitor Interface
2667 
2668 UBF::
2669   Unified Buffer Format it is similar API as Tuxedo's FML
2670 
2671 
2672 ////////////////////////////////////////////////////////////////
2673 The index is normally left completely empty, it's contents being
2674 generated automatically by the DocBook toolchain.
2675 ////////////////////////////////////////////////////////////////