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