Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief ATMI API functions
0003  *
0004  * @file atmi.c
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 #include <string.h>
0035 #include <stdio.h>
0036 #include <stdlib.h>
0037 #include <memory.h>
0038 #include <atmi.h>
0039 
0040 #include <ndrstandard.h>
0041 #include <atmi_tls.h>
0042 #include <atmi_int.h>
0043 #include <ndebug.h>
0044 #include <Exfields.h>
0045 #include <xa_cmn.h>
0046 #include <tperror.h>
0047 #include <atmi_tls.h>
0048 #include <ubf.h>
0049 #include <view2exjson.h>
0050 /*---------------------------Externs------------------------------------*/
0051 /*---------------------------Macros-------------------------------------*/
0052 #define API_ENTRY {ndrx_TPunset_error(); \
0053     /*ATMI_TLS_ENTRY; - no need, as unset error already did.. */\
0054     if (!G_atmi_tls->G_atmi_is_init) { \
0055         /* this means this is dirty client call, do the init */\
0056         NDRX_DBG_INIT(("ATMI", ""));\
0057         entry_status=tpinit(NULL);\
0058     }\
0059 }\
0060 
0061 /** Apply effective next timeout, if any set. TLS is must have  */
0062 #define TIMEOUT_ENTRY   do { G_atmi_tls->tout_next_eff=G_atmi_tls->tout_next;} while (0)
0063 
0064 /** Reset the next timeout. TLS is must have */
0065 #define TIMEOUT_EXIT    do { G_atmi_tls->tout_next=EXFAIL; G_atmi_tls->tout_next_eff=EXFAIL;} while (0)
0066 /*---------------------------Enums--------------------------------------*/
0067 /*---------------------------Typedefs-----------------------------------*/
0068 /*---------------------------Globals------------------------------------*/
0069 /*---------------------------Statics------------------------------------*/
0070 /*---------------------------Prototypes---------------------------------*/
0071 
0072 /**
0073  * API entry for tpacall
0074  * Currently tpacall does not automatically suspend global transaction.
0075  * @param svc
0076  * @param data
0077  * @param len
0078  * @param flags
0079  * @return
0080  */
0081 expublic int tpacall (char *svc, char *data, long len, long flags)
0082 {
0083     int ret=EXSUCCEED;
0084     int entry_status=EXSUCCEED;
0085     
0086     API_ENTRY;
0087     TIMEOUT_ENTRY;
0088     
0089     if (EXSUCCEED!=entry_status)
0090     {
0091         ret=EXFAIL;
0092         goto out;
0093     }
0094     
0095     if (G_atmi_tls->G_atmi_xa_curtx.txinfo && (flags & TPNOREPLY)
0096         /* Bug #827 */
0097         && !(flags & TPNOTRAN))
0098     {
0099         ndrx_TPset_error_msg(TPEINVAL, "Flag TPNOREPLY is not supported in "
0100                 "global transaction mode");
0101         EXFAIL_OUT(ret);
0102     }
0103     
0104     /*flags|=TPNOREPLY;  force that we do not wait for answer! - not needed here really!
0105      causes problems with serice async replies!, See doc for tpacall! */
0106             
0107     /* no reply queue */
0108     ret=ndrx_tpacall(svc, data, len, flags, NULL, EXFAIL, 0, NULL, 0, 0, 0, 0,
0109             NULL);
0110     
0111 out:
0112             
0113     TIMEOUT_EXIT;
0114     return ret;
0115 }
0116 
0117 /**
0118  * Extended version of tpacall, allow extradata + event posting.
0119  * @param svc
0120  * @param data
0121  * @param len
0122  * @param flags
0123  * @param extradata (say user0) string
0124  * @param user1 user data field 1 (only for request)
0125  * @param user2 user data field 2 (only for request)
0126  * @param user3 user data field 3
0127  * @param user4 user data field 4
0128  * @return
0129  */
0130 expublic int tpacallex (char *svc, char *data, 
0131         long len, long flags, char *extradata, int dest_node, int ex_flags,
0132         int user1, long user2, int user3, long user4)
0133 {
0134     int ret=EXSUCCEED;
0135     int entry_status=EXSUCCEED;
0136     
0137     API_ENTRY;
0138     TIMEOUT_ENTRY;
0139 
0140     if (EXSUCCEED!=entry_status)
0141     {
0142         ret=EXFAIL;
0143         goto out;
0144     }
0145     
0146     if (G_atmi_tls->G_atmi_xa_curtx.txinfo && (flags & TPNOREPLY) 
0147         /* Bug #827 */
0148         && !(flags & TPNOTRAN))
0149     {
0150         ndrx_TPset_error_msg(TPEINVAL, "Flag TPNOREPLY is not supported in "
0151                 "global transaction mode");
0152         EXFAIL_OUT(ret);
0153     }
0154 
0155     /*flags|=TPNOREPLY;  force that we do not wait for answer! - not needed here really!
0156      causes problems with serice async replies!, See doc for tpacall! */
0157     
0158     /* no reply queue */
0159     ret=ndrx_tpacall(svc, data, len, flags, extradata, dest_node, ex_flags, 
0160             NULL, user1, user2, user3, user4, NULL);
0161     
0162 out:
0163             
0164     TIMEOUT_EXIT;
0165     return ret;
0166 }
0167 
0168 /**
0169  * API entry for tpalloc
0170  * @param type
0171  * @param subtype
0172  * @param len
0173  * @return
0174  */
0175 expublic char * tpalloc (char *type, char *subtype, long len)
0176 {
0177     char *ret=NULL;
0178     /* int entry_status=EXSUCCEED; */
0179     
0180 /* Allow to skip initialisation - this for for clt init (using tpalloc for buffer request)
0181     API_ENTRY;
0182     if (SUCCEED!=entry_status)
0183     {
0184         ret=NULL;
0185         goto out;
0186     }
0187  */   
0188     /* clear previous errors */
0189     if (NULL!=G_atmi_tls)
0190     {
0191         ndrx_TPunset_error();
0192     }
0193     ret=ndrx_tpalloc(NULL, type, subtype, len);
0194 
0195 out:
0196     return ret;
0197 }
0198 
0199 /**
0200  * API entry for tprealloc
0201  * @param type
0202  * @param subtype
0203  * @param len
0204  * @return
0205  */
0206 expublic char * tprealloc (char *buf, long len)
0207 {
0208     char * ret=NULL;
0209     int entry_status=EXSUCCEED;
0210     
0211     API_ENTRY;
0212     if (EXSUCCEED!=entry_status)
0213     {
0214         ret=NULL;
0215         goto out;
0216     }
0217     
0218     ret=ndrx_tprealloc(buf, len);
0219     
0220 out:
0221     return ret;
0222 }
0223 
0224 /**
0225  * API version of tpcall
0226  * Extended with new flag: TPTRANSUSPEND - suspend global TX in progress.
0227  *          Usable only in sync mode.
0228  * @param svc
0229  * @param idata
0230  * @param ilen
0231  * @param odata
0232  * @param olen
0233  * @param flags
0234  * @return SUCCEED/FAIL
0235  */
0236 expublic int tpcall (char *svc, char *idata, long ilen,
0237                 char **odata, long *olen, long flags)
0238 {
0239     int ret=EXSUCCEED;
0240     int entry_status=EXSUCCEED;
0241     API_ENTRY;
0242 
0243     TIMEOUT_ENTRY;
0244     
0245     if (EXSUCCEED!=entry_status)
0246     {
0247         ret=EXFAIL;
0248         goto out;
0249     }
0250     
0251     /* Check some other parameters */
0252     if (olen==NULL)
0253     {
0254         ndrx_TPset_error_msg(TPEINVAL, "olen cannot be null");
0255         ret=EXFAIL;
0256         goto out;
0257     }
0258     
0259     /* Check some other parameters */
0260     if (odata==NULL)
0261     {
0262         ndrx_TPset_error_msg(TPEINVAL, "odata cannot be null");
0263         ret=EXFAIL;
0264         goto out;
0265     }
0266     
0267     if (flags & TPNOREPLY)
0268     {
0269         ndrx_TPset_error_msg(TPEINVAL, "TPNOREPLY cannot be used with tpcall()");
0270         ret=EXFAIL;
0271         goto out;
0272     }
0273 
0274     ret=ndrx_tpcall (svc, idata, ilen, odata, olen, flags, NULL, 0, 0, 0, 0, 0, 0);
0275     
0276 out:
0277     TIMEOUT_EXIT;
0278     return ret;
0279 }
0280 
0281 /**
0282  * API version of tpgetrply
0283  * @param cd
0284  * @param data
0285  * @param len
0286  * @param flags
0287  * @return SUCCEED/FAIL
0288  */
0289 expublic int tpgetrply (int *cd, char **data, long *len, long flags)
0290 {
0291     int ret=EXSUCCEED;
0292     int entry_status=EXSUCCEED;
0293     API_ENTRY;
0294 
0295     TIMEOUT_ENTRY;
0296     
0297     if (EXSUCCEED!=entry_status)
0298     {
0299         ret=EXFAIL;
0300         goto out;
0301     }
0302 
0303     if (cd==NULL)
0304     {
0305         ndrx_TPset_error_msg(TPEINVAL, "cd cannot be null");
0306         ret=EXFAIL;
0307         goto out;
0308     }
0309 
0310     if (data==NULL)
0311     {
0312         ndrx_TPset_error_msg(TPEINVAL, "data cannot be null");
0313         ret=EXFAIL;
0314         goto out;
0315     }
0316 
0317     if (len==NULL)
0318     {
0319         ndrx_TPset_error_msg(TPEINVAL, "len cannot be null");
0320         ret=EXFAIL;
0321         goto out;
0322     }
0323 
0324     if (flags & TPGETANY)
0325         ret=ndrx_tpgetrply (cd, EXFAIL, data, len, flags, NULL);
0326     else if (*cd <= 0 )
0327     {
0328         ndrx_TPset_error_msg(TPEINVAL, "*cd <= 0");
0329         ret=EXFAIL;
0330         goto out;
0331     }
0332     else if (*cd >= MAX_ASYNC_CALLS )
0333     {
0334         ndrx_TPset_error_fmt(TPEINVAL, "*cd >= %d", MAX_ASYNC_CALLS);
0335         ret=EXFAIL;
0336         goto out;
0337     }
0338     else
0339     {
0340         ret=ndrx_tpgetrply (cd, *cd, data, len, flags, NULL);
0341     }
0342         
0343 out:
0344     
0345     TIMEOUT_EXIT;
0346     return ret;
0347 }
0348 
0349 /**
0350  * API version of tpcall
0351  * @param svc
0352  * @param idata
0353  * @param ilen
0354  * @param odata
0355  * @param olen
0356  * @param flags
0357  * @param extradata - extra data to be passed over the call
0358  * @return SUCCEED/FAIL
0359  */
0360 expublic int tpcallex (char *svc, char *idata, long ilen,
0361                 char * *odata, long *olen, long flags,
0362                 char *extradata, int dest_node, int ex_flags,
0363                 int user1, long user2, int user3, long user4)
0364 {
0365     int ret=EXSUCCEED;
0366     int entry_status=EXSUCCEED;
0367     API_ENTRY;
0368     
0369     TIMEOUT_ENTRY;
0370     if (EXSUCCEED!=entry_status)
0371     {
0372         ret=EXFAIL;
0373         goto out;
0374     }
0375     
0376     /* Check some other parameters */
0377     if (olen==NULL)
0378     {
0379         ndrx_TPset_error_msg(TPEINVAL, "olen cannot be null");
0380         ret=EXFAIL;
0381         goto out;
0382     }
0383     
0384     /* Check some other parameters */
0385     if (odata==NULL)
0386     {
0387         ndrx_TPset_error_msg(TPEINVAL, "odata cannot be null");
0388         ret=EXFAIL;
0389         goto out;
0390     }
0391     
0392     if (flags & TPNOREPLY)
0393     {
0394         ndrx_TPset_error_msg(TPEINVAL, "TPNOREPLY cannot be used with tpcall()");
0395         ret=EXFAIL;
0396         goto out;
0397     }
0398 
0399     ret=ndrx_tpcall (svc, idata, ilen, odata, olen, flags, extradata, 
0400             dest_node, ex_flags, user1, user2, user3, user4);
0401 
0402 out:
0403             
0404     TIMEOUT_EXIT;
0405     return ret;
0406 }
0407 
0408 /**
0409  * Distributed transaction abort.
0410  * @return SUCCED/FAIL
0411  */
0412 expublic int tpabort (long flags)
0413 {
0414     int ret=EXSUCCEED;
0415     int entry_status=EXSUCCEED;
0416     API_ENTRY;
0417     
0418     if (EXSUCCEED!=entry_status)
0419     {
0420         ret=EXFAIL;
0421         goto out;
0422     }
0423     
0424     ret=ndrx_tpabort(flags, EXTRUE);
0425     
0426 out:
0427     return ret;
0428 }
0429 
0430 /**
0431  * Set commit return (ATMI API, see tx_set_commit_return() for tx api)
0432  * @param flags TP_CMT_LOGGED or TP_CMT_COMPLETE
0433  * @return EXSUCCEED/EXFAIL
0434  */
0435 expublic int tpscmt(long flags)
0436 {
0437     int ret=EXSUCCEED;
0438     int entry_status=EXSUCCEED;
0439     API_ENTRY;
0440     
0441     if (EXSUCCEED!=entry_status)
0442     {
0443         ret=EXFAIL;
0444         goto out;
0445     }
0446     
0447     ret=ndrx_tpscmt(flags);
0448     
0449 out:
0450     return ret;
0451 }
0452 
0453 /**
0454  * Fill in transaction info block
0455  * @param txinfo
0456  * @return TX_OK/
0457  */
0458 expublic int tx_info(TXINFO * txinfo)
0459 {
0460     int ret=EXSUCCEED;
0461     int entry_status=EXSUCCEED;
0462     API_ENTRY;
0463     
0464     if (EXSUCCEED!=entry_status)
0465     {
0466         ret=EXFAIL;
0467         goto out;
0468     }
0469     
0470     ret=ndrx_tx_info(txinfo);
0471     
0472 out:
0473     return ret;
0474 }
0475     
0476 /**
0477  * Distributed transaction begin
0478  * @return SUCCEED/FAIL
0479  */
0480 expublic int tpbegin (unsigned long timeout, long flags)
0481 {
0482     int ret=EXSUCCEED;
0483     int entry_status=EXSUCCEED;
0484     API_ENTRY;
0485     
0486     if (EXSUCCEED!=entry_status)
0487     {
0488         ret=EXFAIL;
0489         goto out;
0490     }
0491     
0492     ret=ndrx_tpbegin(timeout, flags);
0493     
0494 out:
0495     return ret;
0496 }
0497 
0498 /**
0499  * Distro transaction commit
0500  * @return SUCCED/FAIL
0501  */
0502 expublic int tpcommit (long flags)
0503 {
0504     int ret=EXSUCCEED;
0505     int entry_status=EXSUCCEED;
0506     API_ENTRY;
0507     
0508     if (EXSUCCEED!=entry_status)
0509     {
0510         ret=EXFAIL;
0511         goto out;
0512     }
0513     
0514     ret=ndrx_tpcommit(flags);
0515     
0516 out:
0517     return ret;
0518 }
0519 
0520 /**
0521  * Open XA interface
0522  * @return SUCCEED/FAIL
0523  */
0524 expublic int tpopen (void)
0525 {
0526     int ret=EXSUCCEED;
0527     int entry_status=EXSUCCEED;
0528     API_ENTRY;
0529     
0530     if (EXSUCCEED!=entry_status)
0531     {
0532         ret=EXFAIL;
0533         goto out;
0534     }
0535     
0536     ret=ndrx_tpopen();
0537     
0538 out:
0539     return ret;
0540 }
0541 
0542 
0543 /**
0544  * Close XA interface
0545  * @return
0546  */
0547 expublic int tpclose (void)
0548 {
0549     int ret=EXSUCCEED;
0550     int entry_status=EXSUCCEED;
0551     
0552     if (NULL==G_atmi_tls || 
0553             !G_atmi_tls->G_atmi_is_init || !G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
0554     {
0555         /* nothing todo */
0556         NDRX_LOG(log_debug, "tp is not open");
0557         goto out;
0558     }
0559     
0560     API_ENTRY;
0561     
0562     if (EXSUCCEED!=entry_status)
0563     {
0564         ret=EXFAIL;
0565         goto out;
0566     }
0567     
0568     ret=ndrx_tpclose();
0569     
0570 out:
0571     return ret;
0572 }
0573 
0574 /**
0575  * Return the current status in global tx or not
0576  * @return  0 - not int tx, 1 - in transaction
0577  */
0578 expublic int tpgetlev (void)
0579 {
0580     ndrx_TPunset_error(); /* this early does TLS entry */
0581 
0582     if (G_atmi_tls->G_atmi_xa_curtx.txinfo)
0583     {
0584         return 1;
0585     }
0586 
0587     return 0;
0588 }
0589 
0590 
0591 /**
0592  * API entry for tpcancel
0593  * @param cd
0594  * @return SUCCEED/FAIL
0595  */
0596 expublic int tpcancel (int cd)
0597 {
0598     int ret=EXSUCCEED;
0599     int entry_status=EXSUCCEED;
0600     API_ENTRY;
0601 
0602     if (EXSUCCEED!=entry_status)
0603     {
0604         ret=EXFAIL;
0605         goto out;
0606     }
0607 
0608     ret=ndrx_tpcancel (cd);
0609 
0610 out:
0611     return ret;
0612 }
0613 
0614 /**
0615  * tpfree implementation
0616  * @param buf
0617  */
0618 expublic void tpfree (char *buf)
0619 {
0620     ndrx_TPunset_error();
0621 
0622     if (NULL!=buf)
0623     {
0624         ndrx_tpfree(buf, NULL);
0625     }
0626     else
0627     {
0628         NDRX_LOG(log_warn, "Trying to tpfree NULL buffer!");
0629     }
0630 }
0631 
0632 /**
0633  * tpisautobuf implementation
0634  * @param buf Typed buffer ptr
0635  * @return TRUE (automatically allocated buffer), FALSE(0) Manually allocated, -1 FAIL
0636  */
0637 expublic int tpisautobuf (char *buf)
0638 {
0639     ndrx_TPunset_error();
0640 
0641     if (NULL!=buf)
0642     {
0643         return ndrx_tpisautobuf(buf);
0644     }
0645     else
0646     {
0647         ndrx_TPset_error_msg(TPEINVAL, "Null buffer passed to tpisautobuf()!");
0648         return EXFAIL;
0649     }
0650 }
0651 
0652 /**
0653  * tpterm API entry.
0654  * We do not do standard initailization.
0655  * Intentionally we do not do API init here, because we do not wan't that
0656  * queue gets open for nothing (if this is first API call?)
0657  * Only not sure how about debug?
0658  * @return SUCCEED/FAIL
0659  */
0660 expublic int tpterm (void)
0661 {
0662     ndrx_TPunset_error();
0663     return ndrx_tpterm();
0664 }
0665 
0666 /**
0667  * API version of tpconnect
0668  * @param svc
0669  * @param data
0670  * @param len
0671  * @param flags
0672  * @return
0673  */
0674 expublic int tpconnect (char *svc, char *data, long len, long flags)
0675 {
0676     int ret=EXSUCCEED;
0677     int entry_status=EXSUCCEED;
0678     API_ENTRY;
0679 
0680     if (EXSUCCEED!=entry_status)
0681     {
0682         ret=EXFAIL;
0683         goto out;
0684     }
0685     
0686     ret=ndrx_tpconnect (svc, data, len, flags);
0687 
0688 out:
0689     return ret;
0690 }
0691 
0692 /**
0693  * API version of tprecv
0694  * @param cd
0695  * @param data
0696  * @param len
0697  * @param flags
0698  * @param revent
0699  * @param command_id
0700  * @return
0701  */
0702 expublic int tprecv (int cd, char **data,
0703                         long *len, long flags, long *revent)
0704 {
0705     int ret=EXSUCCEED;
0706     int entry_status=EXSUCCEED;
0707     short command_id=ATMI_COMMAND_CONVDATA;
0708     API_ENTRY;
0709 
0710     if (EXSUCCEED!=entry_status)
0711     {
0712         ret=EXFAIL;
0713         goto out;
0714     }
0715 
0716     /* Check some other parameters */
0717     if (data==NULL)
0718     {
0719         ndrx_TPset_error_msg(TPEINVAL, "data cannot be null");
0720         ret=EXFAIL;
0721         goto out;
0722     }
0723 /*
0724     we provider internal len buffer if needed
0725     if (len==NULL)
0726     {
0727         ndrx_TPset_error_msg(TPEINVAL, "len cannot be null");
0728         ret=EXFAIL;
0729         goto out;
0730     }
0731 */
0732 
0733     ret=ndrx_tprecv (cd, data, len, flags, revent, &command_id, EXFALSE);
0734 
0735 out:
0736     return ret;
0737 }
0738 
0739 /**
0740  * API version of tpsend
0741  * @param cd
0742  * @param data
0743  * @param len
0744  * @param flags
0745  * @param revent
0746  * @return
0747  */
0748 expublic int tpsend (int cd, char *data, long len, long flags,
0749                                     long *revent)
0750 {
0751     int ret=EXSUCCEED;
0752     int entry_status=EXSUCCEED;
0753     API_ENTRY;
0754 
0755     if (EXSUCCEED!=entry_status)
0756     {
0757         ret=EXFAIL;
0758         goto out;
0759     }
0760 
0761     ret=ndrx_tpsend (cd, data, len, flags, revent, ATMI_COMMAND_CONVDATA);
0762 
0763 out:
0764     return ret;
0765 }
0766 
0767 /**
0768  * API version of tpdiscon
0769  * @param cd
0770  * @param data
0771  * @param len
0772  * @param flags
0773  * @param revent
0774  * @return
0775  */
0776 expublic int tpdiscon (int cd)
0777 {
0778     int ret=EXSUCCEED;
0779     int entry_status=EXSUCCEED;
0780     API_ENTRY;
0781 
0782     if (EXSUCCEED!=entry_status)
0783     {
0784         ret=EXFAIL;
0785         goto out;
0786     }
0787 
0788     ret=ndrx_tpdiscon (cd);
0789 
0790 out:
0791     return ret;
0792 }
0793 
0794 /**
0795  * API version of tppost
0796  * @param eventname
0797  * @param data
0798  * @param len
0799  * @param flags
0800  * @return
0801  */
0802 expublic int tppost(char *eventname, char *data, long len, long flags)
0803 {
0804     long ret=EXSUCCEED;
0805     int entry_status=EXSUCCEED;
0806     API_ENTRY;
0807 
0808     if (EXSUCCEED!=entry_status)
0809     {
0810         ret=EXFAIL;
0811         goto out;
0812     }
0813 
0814     ret=ndrx_tppost(eventname, data, len, flags, 0, 0, 0, 0);
0815 
0816 out:
0817     return ret;
0818 }
0819 
0820 /**
0821  * API entry for tpsubscribe
0822  */
0823 expublic long tpsubscribe(char *eventexpr, char *filter, TPEVCTL *ctl, long flags)
0824 {
0825     long ret=EXSUCCEED;
0826     int entry_status=EXSUCCEED;
0827     API_ENTRY;
0828 
0829     if (EXSUCCEED!=entry_status)
0830     {
0831         ret=EXFAIL;
0832         goto out;
0833     }
0834 
0835     ret=ndrx_tpsubscribe(eventexpr, filter, ctl, flags);
0836 
0837 out:
0838     return ret;
0839 }
0840 
0841 /**
0842  * API version of tpunsubscribe
0843  */
0844 expublic int tpunsubscribe(long subscription, long flags)
0845 {
0846     long ret=EXSUCCEED;
0847     int entry_status=EXSUCCEED;
0848     API_ENTRY;
0849 
0850     if (EXSUCCEED!=entry_status)
0851     {
0852         ret=EXFAIL;
0853         goto out;
0854     }
0855 
0856     ret=ndrx_tpunsubscribe(subscription, flags);
0857 
0858 out:
0859     return ret;
0860 }
0861 
0862 /**
0863  * Convert Enduro/X identifier to string representation
0864  * @param str in/out string version of identifier
0865  * @param bin in/out binary version of identifier
0866  * @param flags (TPCONVCLTID or TPCONVTRANID or TPCONVXID) and TPTOSTRING
0867  * @return EXSUCCEED/EXFAIL
0868  */
0869 expublic int tpconvert (char *str, char *bin, long flags)
0870 {
0871     int ret=EXSUCCEED;
0872     int entry_status=EXSUCCEED;
0873     API_ENTRY;
0874 
0875     if (EXSUCCEED!=entry_status)
0876     {
0877         EXFAIL_OUT(ret);
0878     }
0879     
0880     /* Check arguments */
0881     if (NULL==str)
0882     {
0883         ndrx_TPset_error_msg(TPEINVAL, "`str' must not be NULL");
0884         EXFAIL_OUT(ret);
0885     }
0886     
0887     if (NULL==bin)
0888     {
0889         ndrx_TPset_error_msg(TPEINVAL, "`bin' must not be NULL");
0890         EXFAIL_OUT(ret);
0891     }
0892     
0893     /* check the string value in case if converting from string to bin */
0894     if (!(flags & TPTOSTRING))
0895     {
0896         /* so we are converting from string -> bin. The string must not be empty */
0897         if (EXEOS==str[0])
0898         {
0899             ndrx_TPset_error_msg(TPEINVAL, "Converting from string, `str' is empty!");
0900             EXFAIL_OUT(ret);
0901         }
0902     }
0903     
0904     ret=ndrx_tpconvert(str, bin, flags);
0905             
0906 out:
0907     return ret;    
0908 }
0909 
0910 /**
0911  * Suspend global XA transaction
0912  * @param tranid
0913  * @param flags
0914  * @return SUCCEED/FAIL
0915  */
0916 expublic int tpsuspend (TPTRANID *tranid, long flags) 
0917 {
0918     int ret=EXSUCCEED;
0919     int entry_status=EXSUCCEED;
0920     API_ENTRY;
0921 
0922     if (EXSUCCEED!=entry_status)
0923     {
0924         ret=EXFAIL;
0925         goto out;
0926     }
0927     
0928     ret = ndrx_tpsuspend (tranid, flags, EXFALSE);
0929     
0930 out:
0931     return ret;
0932 }
0933 
0934 /**
0935  * Resume global XA transaction
0936  * @param tranid
0937  * @param flags
0938  * @return SUCCEED/FAIL
0939  */
0940 expublic int tpresume (TPTRANID *tranid, long flags)
0941 {
0942     int ret=EXSUCCEED;
0943     int entry_status=EXSUCCEED;
0944     API_ENTRY;
0945 
0946     if (EXSUCCEED!=entry_status)
0947     {
0948         ret=EXFAIL;
0949         goto out;
0950     }
0951     
0952     ret = ndrx_tpresume (tranid, flags);
0953     
0954 out:
0955     return ret;
0956 }
0957 
0958 /**
0959  * Return type information to caller.
0960  * The buffer must be allocated by tpalloc.
0961  * @param ptr ATMI buffer to test
0962  * @param type unload type to ()
0963  * @param subtype unload sub-type to
0964  * @return number of bytes allocated (or -1 on failure)
0965  */
0966 expublic long tptypes (char *ptr, char *type, char *subtype)
0967 {
0968     long ret=EXSUCCEED;
0969     int entry_status=EXSUCCEED;
0970     API_ENTRY;
0971 
0972     if (EXSUCCEED!=entry_status)
0973     {
0974         ret=EXFAIL;
0975         goto out;
0976     }
0977    /* 
0978     * we allow to get infos for null, the type will be NULL
0979     if (ptr==NULL)
0980     {
0981         ndrx_TPset_error_msg(TPEINVAL, "ptr cannot be null");
0982         ret=EXFAIL;
0983         goto out;
0984     }
0985     */
0986 
0987     ret=ndrx_tptypes(ptr, type, subtype);
0988 
0989 out:
0990     return ret;
0991 }
0992 
0993 
0994 /**
0995  * Return current node id
0996  * @return FAIL = error, >0 node id.
0997  */
0998 expublic long tpgetnodeid(void)
0999 {
1000     long ret=EXSUCCEED;
1001     int entry_status=EXSUCCEED;
1002     API_ENTRY;
1003 
1004     if (EXSUCCEED!=entry_status)
1005     {
1006         ret=EXFAIL;
1007         goto out;
1008     }
1009     
1010     ret = G_atmi_env.our_nodeid;
1011     
1012 out:
1013     return ret;
1014 }
1015 
1016 /**
1017  * Convert JSON to UBF
1018  * @param p_ub  output UBF
1019  * @param buffer    input buffer
1020  * @return 
1021  */
1022 expublic int tpjsontoubf(UBFH *p_ub, char *buffer)
1023 {
1024     int ret=EXSUCCEED;
1025     int entry_status=EXSUCCEED;
1026     API_ENTRY;
1027     
1028     ret = ndrx_tpjsontoubf(p_ub, buffer, NULL);
1029     
1030 out:
1031     return ret;
1032 }
1033 
1034 /**
1035  * Convert UBF to JSON text
1036  * @param p_ub
1037  * @param buffer
1038  * @param bufsize
1039  * @return 
1040  */
1041 expublic int tpubftojson(UBFH *p_ub, char *buffer, int bufsize)
1042 {
1043     int ret=EXSUCCEED;
1044     int entry_status=EXSUCCEED;
1045     API_ENTRY;
1046     
1047     ret=ndrx_tpubftojson(p_ub, buffer, bufsize, NULL);
1048     
1049 out:
1050     return ret;
1051 }
1052 
1053 /**
1054  * Enqueue message
1055  */
1056 expublic int tpenqueue (char *qspace, char *qname, TPQCTL *ctl, char *data, long len, long flags)
1057 {   
1058     long ret=EXSUCCEED;
1059     int entry_status=EXSUCCEED;
1060     API_ENTRY;
1061 
1062     if (EXSUCCEED!=entry_status)
1063     {
1064         ret=EXFAIL;
1065         goto out;
1066     }
1067     
1068     ret=ndrx_tpenqueue (qspace, 0, 0, qname, ctl, data, len, flags);
1069 
1070 out:
1071     return ret;
1072 
1073 }
1074 
1075 /**
1076  * Dequeue message
1077  */
1078 expublic int tpdequeue (char *qspace, char *qname, TPQCTL *ctl, char **data, long *len, long flags)
1079 {
1080     long ret=EXSUCCEED;
1081     int entry_status=EXSUCCEED;
1082     API_ENTRY;
1083 
1084     if (EXSUCCEED!=entry_status)
1085     {
1086         ret=EXFAIL;
1087         goto out;
1088     }
1089     
1090     ret=ndrx_tpdequeue (qspace, 0, 0, qname, ctl, data, len, flags);
1091 
1092 out:
1093     return ret;
1094 }
1095 
1096 /**
1097  * Enqueue message
1098  */
1099 expublic int tpenqueueex (short nodeid, short srvid, char *qname, TPQCTL *ctl, 
1100         char *data, long len, long flags)
1101 {   
1102     long ret=EXSUCCEED;
1103     int entry_status=EXSUCCEED;
1104     API_ENTRY;
1105 
1106     if (EXSUCCEED!=entry_status)
1107     {
1108         ret=EXFAIL;
1109         goto out;
1110     }
1111     
1112     ret=ndrx_tpenqueue ("", nodeid, srvid, qname, ctl, data, len, flags);
1113 
1114 out:
1115     return ret;
1116 
1117 }
1118 
1119 /**
1120  * Dequeue message
1121  */
1122 expublic int tpdequeueex (short nodeid, short srvid, char *qname, TPQCTL *ctl, char **data, long *len, long flags)
1123 {
1124     long ret=EXSUCCEED;
1125     int entry_status=EXSUCCEED;
1126     API_ENTRY;
1127 
1128     if (EXSUCCEED!=entry_status)
1129     {
1130         ret=EXFAIL;
1131         goto out;
1132     }
1133     
1134     ret=ndrx_tpdequeue ("", nodeid, srvid, qname, ctl, data, len, flags);
1135 
1136 out:
1137     return ret;
1138 }
1139 
1140 /* Internal API: */
1141 
1142 /**
1143  * For AIX we have issues with global variable exports
1144  * But functions work..
1145  * @return 
1146  */
1147 expublic tp_command_call_t *ndrx_get_G_last_call(void)
1148 {
1149     ATMI_TLS_ENTRY;
1150     
1151     return &G_atmi_tls->G_last_call;
1152 }
1153 
1154 /**
1155  * Access to atmi lib conf
1156  * @return 
1157  */
1158 expublic atmi_lib_conf_t *ndrx_get_G_atmi_conf(void)
1159 {
1160     ATMI_TLS_ENTRY;
1161     return &G_atmi_tls->G_atmi_conf;
1162 }
1163 
1164 /**
1165  * Access to to atmi lib env globals
1166  * @return 
1167  */
1168 expublic atmi_lib_env_t *ndrx_get_G_atmi_env(void)
1169 {
1170     return &G_atmi_env;
1171 }
1172 
1173 /**
1174  * Get current ATMI transaction object
1175  * @return 
1176  */
1177 expublic atmi_xa_curtx_t *ndrx_get_G_atmi_xa_curtx(void)
1178 {
1179     ATMI_TLS_ENTRY;
1180     return &G_atmi_tls->G_atmi_xa_curtx;
1181 }
1182 
1183 /**
1184  * Get accepted connection ATMI object
1185  * @return 
1186  */
1187 expublic tp_conversation_control_t *ndrx_get_G_accepted_connection(void)
1188 {
1189     ATMI_TLS_ENTRY;
1190     
1191     return &G_atmi_tls->G_accepted_connection;
1192 }
1193 
1194 /**
1195  * Kill the given context
1196  * @param context
1197  * @param flags
1198  * @return 
1199  */
1200 expublic void tpfreectxt(TPCONTEXT_T context)
1201 {
1202     ndrx_tpfreectxt(context);
1203 }
1204 
1205 /**
1206  * Set Enduro/X context for current thread
1207  * @param context
1208  * @param flags
1209  * @return 
1210  */
1211 expublic int tpsetctxt(TPCONTEXT_T context, long flags)
1212 {
1213     int ret=EXSUCCEED;
1214     int entry_status=EXSUCCEED;
1215     /* API_ENTRY; */
1216 
1217     if (EXSUCCEED!=entry_status)
1218     {
1219         ret=EXFAIL;
1220         goto out;
1221     }
1222     
1223     ret = ndrx_tpsetctxt(context, flags, (CTXT_PRIV_NSTD|CTXT_PRIV_UBF|
1224             CTXT_PRIV_ATMI|CTXT_PRIV_TRAN));
1225     
1226 out:
1227     return ret;
1228 }
1229 
1230 /**
1231  * Get the current context
1232  * This disconnects current thread from TLS.
1233  * @param flags
1234  * @return 
1235  */
1236 expublic int tpgetctxt(TPCONTEXT_T *context, long flags)
1237 {
1238     int ret=EXSUCCEED;
1239     int entry_status=EXSUCCEED;
1240     /* API_ENTRY; */
1241 
1242     if (EXSUCCEED!=entry_status)
1243     {
1244         ret=EXFAIL;
1245         goto out;
1246     }
1247     
1248     ret = ndrx_tpgetctxt(context, flags, (CTXT_PRIV_NSTD|CTXT_PRIV_UBF|
1249             CTXT_PRIV_ATMI|CTXT_PRIV_TRAN));
1250     
1251 out:
1252     return ret;
1253 }
1254 
1255 
1256 /**
1257  * Get the current context
1258  * This disconnects current thread from TLS.
1259  * We will allocate the NSTD & UBF TLSes too
1260  * @param flags
1261  * @return 
1262  */
1263 expublic TPCONTEXT_T tpnewctxt(int auto_destroy, int auto_set)
1264 {
1265     TPCONTEXT_T ctx = ndrx_atmi_tls_new(NULL, auto_destroy, auto_set);
1266     
1267     if (NULL!=ctx)
1268     {
1269         atmi_tls_t * ac = (atmi_tls_t *)ctx;
1270         
1271         ac->p_nstd_tls = ndrx_nstd_tls_new(auto_destroy, auto_set);
1272         ac->p_ubf_tls = ndrx_ubf_tls_new(auto_destroy, auto_set);
1273     }
1274     
1275     return ctx;
1276 }
1277 
1278 /**
1279  * Set the request logfile
1280  * - If data exists and filename exists, then update data buffer and set active 
1281  *      request logfile to filename
1282  * - If data does not exists, and filename exists, then set active request logfile
1283  *      to filename
1284  * @param data XATMI buffer
1285  * @param filename new logfile (if no data, then this is source for filename).
1286  * @param filesvc filename service (optional) - call the XATMI server for 
1287  *              generating file name and putting into buffer
1288  * @return SUCCEED/FAIL
1289  */
1290 expublic int tplogsetreqfile(char **data, char *filename, char *filesvc)
1291 {
1292     int ret=EXSUCCEED;
1293     int entry_status=EXSUCCEED;
1294     API_ENTRY;
1295 
1296     if (EXSUCCEED!=entry_status)
1297     {
1298         EXFAIL_OUT(ret);
1299     }
1300     
1301     ret = ndrx_tplogsetreqfile(data, filename, filesvc);
1302     
1303 out:
1304     return ret;
1305 }
1306 
1307 /**
1308  * Print UBF buffer to logger
1309  * @param lev logging level to start print at
1310  * @param title title of the dump
1311  * @param p_ub UBF buffer
1312  */
1313 expublic void tplogprintubf(int lev, char *title, UBFH *p_ub)
1314 {
1315     ndrx_tplogprintubf(lev, title, p_ub);
1316 }
1317 
1318 /**
1319  * Get the filename from buffer ()
1320  * @param data
1321  * @param filename
1322  * @return SUCCEED (have filename in buffer, 
1323  */
1324 expublic int tploggetbufreqfile(char *data, char *filename, int bufsize)
1325 {
1326     int ret=EXSUCCEED;
1327     int entry_status=EXSUCCEED;
1328     API_ENTRY;
1329     
1330     if (EXSUCCEED!=entry_status)
1331     {
1332         EXFAIL_OUT(ret);
1333     }
1334     
1335     ret = ndrx_tploggetbufreqfile(data, filename, bufsize);
1336     
1337 out:
1338     return ret;
1339 }
1340 
1341 /**
1342  * Delete the request file from buffer
1343  * @param data XATMI buffer
1344  * @return SUCCEED (have filename in buffer, 
1345  */
1346 expublic int tplogdelbufreqfile(char *data)
1347 {
1348     int ret=EXSUCCEED;
1349     int entry_status=EXSUCCEED;
1350     API_ENTRY;
1351 
1352     if (EXSUCCEED!=entry_status)
1353     {
1354         EXFAIL_OUT(ret);
1355     }
1356     
1357     ret = ndrx_tplogdelbufreqfile(data);
1358     
1359 out:
1360     return ret;
1361 }
1362 
1363 
1364 /**
1365  * Admin call interface, not yet supported.
1366  * TODO: Implement admin call at the current version
1367  * @param inbuf
1368  * @param outbuf
1369  * @param flags
1370  * @return 
1371  */
1372 expublic int tpadmcall(UBFH *inbuf, UBFH **outbuf, long flags)
1373 {
1374     long ret=EXSUCCEED;
1375     int entry_status=EXSUCCEED;
1376     API_ENTRY;
1377 
1378     if (EXSUCCEED!=entry_status)
1379     {
1380         ret=EXFAIL;
1381         goto out;
1382     }   
1383     ndrx_TPset_error_msg(TPENOENT, "TODO: tpadmcall: Not yet implemented.");
1384     ret = EXFAIL;
1385 
1386 out:
1387     return ret;
1388 }
1389 
1390 /**
1391  * Retrieve metadata associated with the call.
1392  * 
1393  * @param msg buffer to measure
1394  * @param cibuf field container. This point to NULL or ATMI allocated buffer
1395  * @param flags RFU
1396  * @return EXFAIL
1397  */
1398 expublic int tpgetcallinfo(const char *msg, UBFH **cibuf, long flags)
1399 {
1400     long ret=EXSUCCEED;
1401     int entry_status=EXSUCCEED;
1402     API_ENTRY;
1403 
1404     if (EXSUCCEED!=entry_status)
1405     {
1406         ret=EXFAIL;
1407         goto out;
1408     }   
1409     
1410     if (NULL==msg)
1411     {
1412         ndrx_TPset_error_fmt(TPEINVAL, "msg call buffer cannot be NULL", msg);
1413         EXFAIL_OUT(ret);   
1414     }
1415     
1416     /* we will realloc correspondingly */
1417     if (NULL==cibuf)
1418     {
1419         ndrx_TPset_error_fmt(TPEINVAL, "cibuf cannot be null NULL", msg);
1420         EXFAIL_OUT(ret);   
1421     }
1422     
1423     if (0!=flags && flags!=TPCI_NOEOFERR)
1424     {
1425         ndrx_TPset_error_fmt(TPEINVAL, "Flags (%ld) must be 0 or TPCI_NOEOFERR", flags);
1426         EXFAIL_OUT(ret);
1427     }
1428     
1429     ret=ndrx_tpgetcallinfo(msg, cibuf, flags);
1430 
1431 out:
1432     return ret;
1433 }
1434 
1435 /**
1436  * Attach headers infos to the call
1437  * @param msg message to which attach meta data
1438  * @param cibuf meta data storage
1439  * @param flags RFU
1440  * @return EXFAIL
1441  */
1442 expublic int tpsetcallinfo(const char *msg, UBFH *cibuf, long flags)
1443 {
1444     long ret=EXSUCCEED;
1445     int entry_status=EXSUCCEED;
1446     
1447     /* reset the error & allocate TLS if needed */
1448     ndrx_TPunset_error();
1449 
1450     if (EXSUCCEED!=entry_status)
1451     {
1452         ret=EXFAIL;
1453         goto out;
1454     }   
1455     
1456     if (!Bisubf(cibuf))
1457     {
1458         ndrx_TPset_error_fmt(TPEINVAL, "obuf %p is not UBF", cibuf);
1459         EXFAIL_OUT(ret);   
1460     }
1461     
1462     if (NULL==msg)
1463     {
1464         ndrx_TPset_error_fmt(TPEINVAL, "msg call buffer cannot be NULL", msg);
1465         EXFAIL_OUT(ret);   
1466     }
1467     
1468     if (0!=flags)
1469     {
1470         ndrx_TPset_error_fmt(TPEINVAL, "Flags (%ld) must be 0", flags);
1471         EXFAIL_OUT(ret);
1472     }
1473     
1474     ret=ndrx_tpsetcallinfo(msg, cibuf, flags);
1475 
1476 out:
1477     return ret;
1478 }
1479 
1480 /**
1481  * We do not work in auth mode.
1482  * @return FAIL
1483  */
1484 expublic int tpchkauth(void)
1485 {
1486     int ret=EXSUCCEED;
1487     int entry_status=EXSUCCEED;
1488     API_ENTRY;
1489 
1490     if (EXSUCCEED!=entry_status)
1491     {
1492         ret=EXFAIL;
1493         goto out;
1494     }   
1495     
1496     ret = TPNOAUTH;
1497 
1498 out:
1499     return ret;
1500 }
1501 
1502 
1503 /**
1504  * STUB for tpnotify()
1505  * @param clientid
1506  * @param data
1507  * @param len
1508  * @param flags
1509  * @return FAIL
1510  */
1511 expublic int tpnotify(CLIENTID *clientid, char *data, long len, long flags)
1512 {
1513     int ret=EXSUCCEED;
1514     int entry_status=EXSUCCEED;
1515     TPMYID myid;
1516     API_ENTRY;
1517 
1518     if (EXSUCCEED!=entry_status)
1519     {
1520         EXFAIL_OUT(ret);
1521     }   
1522     
1523     if (NULL==clientid)
1524     {
1525         NDRX_LOG(log_error, "%s: clientid is NULL!", __func__);
1526         ndrx_TPset_error_msg(TPEINVAL, "clientid is NULL!");
1527         
1528         EXFAIL_OUT(ret);
1529     }
1530     
1531     if (EXSUCCEED!=ndrx_myid_parse(clientid->clientdata, &myid, EXFALSE))
1532     {
1533         NDRX_LOG(log_error, "%s: Failed to parse my_id!", __func__);
1534         ndrx_TPset_error_fmt(TPEINVAL, "Failed to parse: [%s]", clientid->clientdata);
1535         
1536         EXFAIL_OUT(ret);
1537     }
1538        
1539     if (EXSUCCEED!=ndrx_tpnotify(clientid, &myid, NULL, data, len, flags,
1540             myid.nodeid, NULL, NULL, NULL, 0L))
1541     {
1542         NDRX_LOG(log_error, "_tpnotify - failed!");
1543         EXFAIL_OUT(ret);
1544     }
1545 
1546 out:
1547 
1548     NDRX_LOG(log_debug, "%s returns %d", __func__, ret);
1549 
1550     return ret;
1551 }
1552 
1553 /**
1554  * Set handler for unsolicited messages
1555  * @param disp message hander (if processing allowed) or NULL (if no delivery needed)
1556  * @return previous handler
1557  */
1558 expublic void (*tpsetunsol (void (*disp) (char *data, long len, long flags))) (char *data, long len, long flags)
1559 {
1560     void * ret=NULL;
1561     int entry_status=EXSUCCEED;
1562     API_ENTRY;
1563             
1564     if (EXSUCCEED!=entry_status)
1565     {
1566         ret=(void *)TPUNSOLERR;
1567         goto out;
1568     }
1569     
1570     ret = (void *)G_atmi_tls->p_unsol_handler;
1571     
1572     G_atmi_tls->p_unsol_handler = disp;
1573     
1574     NDRX_LOG(log_debug, "%s: new disp=%p old=%p", 
1575             __func__, G_atmi_tls->p_unsol_handler, ret);
1576 
1577 out:
1578     return (void (*) (char *, long, long))ret;
1579 }
1580 
1581 /**
1582  * Return constant for tpsetunsol()
1583  * @param data
1584  * @param len
1585  * @param flags
1586  */
1587 expublic void ndrx_ndrx_tmunsolerr_handler (char *data, long len, long flags)
1588 {
1589     NDRX_LOG(log_debug, "ndrx_ndrx_tmunsolerr_handler() - TPUNSOLERR called");
1590 }
1591 
1592 /**
1593  * Check unsolicited messages by client
1594  * @return -1 on error, or number of messages processed
1595  */
1596 expublic int tpchkunsol(void) 
1597 {
1598     int ret=EXSUCCEED;
1599     int entry_status=EXSUCCEED;
1600     API_ENTRY;
1601 
1602     if (EXSUCCEED!=entry_status)
1603     {
1604         EXFAIL_OUT(ret);
1605     }   
1606     
1607     /* Bug #269 - return the number of messages processed... 
1608      * The default mode is not blocked.
1609      */
1610     ret=ndrx_tpchkunsol(TPNOBLOCK);
1611     
1612     if (ret<0)
1613     {
1614         NDRX_LOG(log_error, "ndrx_tpchkunsol failed");
1615         EXFAIL_OUT(ret);
1616     }
1617 
1618 out:
1619     return ret;
1620 }
1621 
1622 /**
1623  * Broadcast the message to matched clients
1624  * @param lmid optional nodeid can be NULL (matches all), emtpy (matches all), 
1625  * or exact match or regexp match.
1626  * @param usrname not used can be null or set or empty
1627  * @param cltname client name can be NULL or empty (matches all). Or regexp match
1628  * @param data tpalloc allocated buffer
1629  * @param len data len
1630  * @param flags flags like TPNOBLOCK and TPREGEXMATCH
1631  * @return SUCCEED/FAIL
1632  */
1633 expublic int tpbroadcast(char *lmid, char *usrname, char *cltname,
1634   char *data,  long len, long flags)
1635 {
1636     int ret=EXSUCCEED;
1637     int entry_status=EXSUCCEED;
1638     API_ENTRY;
1639 
1640     if (EXSUCCEED!=entry_status)
1641     {
1642         EXFAIL_OUT(ret);
1643     }   
1644     
1645     if (EXSUCCEED!=ndrx_tpbroadcast_local(lmid, usrname, cltname, 
1646             data,  len, flags, 0))
1647     {
1648         NDRX_LOG(log_error, "ndrx_tpbroadcast_local failed");
1649         EXFAIL_OUT(ret);
1650     }
1651 
1652 out:
1653     return ret;
1654 }
1655 
1656 /**
1657  * Convert view to JSON
1658  * @param cstruct view object
1659  * @param view view name
1660  * @param buffer output buffer
1661  * @param bufsize output buffer size
1662  * @param flags 0 or BVACCESS_NOTNULL for NULL access mode
1663  * @return 0 on succeed, -1 on fail
1664  */
1665 expublic int tpviewtojson(char *cstruct, char *view, char *buffer,  
1666         int bufsize, long flags)
1667 {
1668     int ret=EXSUCCEED;
1669     int entry_status=EXSUCCEED;
1670     API_ENTRY;
1671     
1672     if (NULL==cstruct)
1673     {
1674         NDRX_LOG(log_error, "cstruct is NULL");
1675         ndrx_TPset_error_fmt(TPEINVAL, "cstruct is NULL");
1676         EXFAIL_OUT(ret);
1677     }
1678     
1679     if (NULL==view || EXEOS==view[0])
1680     {
1681         NDRX_LOG(log_error, "view is NULL or empty");
1682         ndrx_TPset_error_fmt(TPEINVAL, "view is NULL or empty");
1683         EXFAIL_OUT(ret);
1684     }
1685     
1686     if (NULL==buffer)
1687     {
1688         NDRX_LOG(log_error, "buffer is NULL");
1689         ndrx_TPset_error_fmt(TPEINVAL, "buffer is NULL");
1690         EXFAIL_OUT(ret);
1691     }
1692     
1693     
1694     ret = ndrx_tpviewtojson(cstruct, view, buffer,  bufsize, flags, NULL);
1695     
1696 out:
1697     return ret;
1698 }
1699 
1700 /**
1701  * Convert json to view 
1702  * @param view view name (output)
1703  * @param buffer input buffer to parse
1704  * @return NULL on error, or tpalloc'd VIEW buffer with parsed fields inside.
1705  */
1706 expublic char* tpjsontoview(char *view, char *buffer)
1707 {
1708     int ret=EXSUCCEED;
1709     char *ret_ptr;
1710     int entry_status=EXSUCCEED;
1711     API_ENTRY;
1712     
1713     if (NULL==view)
1714     {
1715         NDRX_LOG(log_error, "view is NULL");
1716         ndrx_TPset_error_fmt(TPEINVAL, "view is NULL");
1717         EXFAIL_OUT(ret);
1718     }
1719     
1720     if (NULL==buffer)
1721     {
1722         NDRX_LOG(log_error, "buffer is NULL");
1723         ndrx_TPset_error_fmt(TPEINVAL, "buffer is NULL");
1724         EXFAIL_OUT(ret);
1725     }
1726     
1727     ret_ptr=ndrx_tpjsontoview(view, buffer, NULL, NULL);
1728     
1729 out:
1730     if (EXSUCCEED==ret)
1731     {
1732         return ret_ptr;
1733     }
1734     else
1735     {
1736         return NULL;
1737     }
1738 }
1739 
1740 /**
1741  * Set ATMI timeout (for tpcall send & receive)
1742  * WARNING ! No init performed, if called befor tpinit(), you may expect
1743  * that results will be overwritten by tpinit().
1744  * @param tout number of seconds to wait
1745  * @return EXSUCCED/EXFAIL (tpinit fail)
1746  */
1747 expublic int tptoutset(int tout)
1748 {    
1749     int ret=EXSUCCEED;
1750     
1751     if (tout <=0 )
1752     {
1753         ndrx_TPset_error_fmt(TPEINVAL, "tout is <= 0");
1754         EXFAIL_OUT(ret);
1755     }
1756         
1757     ndrx_tptoutset(tout);
1758     
1759 out:
1760     return ret;
1761 }
1762 
1763 /**
1764  * Get current timeout configuration
1765  * @return EXUSCEED/EXFAIL (in case of tpinit fail)
1766  */
1767 expublic int tptoutget(void)
1768 {
1769     int ret;
1770     
1771     ret=ndrx_tptoutget();
1772     
1773 out:
1774     return ret;
1775 }
1776 
1777 /**
1778  * Convert an JSON representation of a message into a typed message buffer 
1779  * @param istr JSON representation of a message 
1780  * @param ilen contains the length of the binary data contained in istr
1781  * @param obuf typed message buffer
1782  * @param olen amount of valid data contained in the output buffer
1783  * @param flags 
1784  * @return 
1785  */
1786 expublic int tpimport(char *istr, long ilen, char **obuf, long *olen, long flags)
1787 {
1788     int ret=EXSUCCEED;
1789     int entry_status=EXSUCCEED;
1790     API_ENTRY;
1791 
1792     if (EXSUCCEED!=entry_status)
1793     {
1794         EXFAIL_OUT(ret);
1795     }
1796 
1797     /* Check some other parameters */
1798     if (istr==NULL)
1799     {
1800         ndrx_TPset_error_msg(TPEINVAL, "istr cannot be null");
1801         EXFAIL_OUT(ret);
1802     }
1803 
1804     /* Check some other parameters */
1805     if (obuf==NULL)
1806     {
1807         ndrx_TPset_error_msg(TPEINVAL, "obuf cannot be null");
1808         EXFAIL_OUT(ret);
1809     }
1810 
1811     ret=ndrx_tpimportex(NULL, istr, ilen, obuf, olen, flags, NULL);
1812 
1813 out:
1814     return ret;
1815 }
1816 
1817 /**
1818  * Convert an JSON representation of a message into a typed message buffer 
1819  * @param bufctl
1820  * @param istr JSON representation of a message 
1821  * @param ilen contains the length of the binary data contained in istr
1822  * @param obuf typed message buffer
1823  * @param olen amount of valid data contained in the output buffer
1824  * @param flags
1825  * @return 
1826  */
1827 expublic int tpimportex(ndrx_expbufctl_t *bufctl, char *istr, long ilen, char **obuf, long *olen, long flags)
1828 {
1829     int ret=EXSUCCEED;
1830     int entry_status=EXSUCCEED;
1831     API_ENTRY;
1832 
1833     if (EXSUCCEED!=entry_status)
1834     {
1835         EXFAIL_OUT(ret);
1836     }
1837 
1838     /* Check some other parameters */
1839     if (istr==NULL)
1840     {
1841         ndrx_TPset_error_msg(TPEINVAL, "istr cannot be null");
1842         EXFAIL_OUT(ret);
1843     }
1844 
1845     /* Check some other parameters */
1846     if (obuf==NULL)
1847     {
1848         ndrx_TPset_error_msg(TPEINVAL, "obuf cannot be null");
1849         EXFAIL_OUT(ret);
1850     }
1851 
1852     ret=ndrx_tpimportex(bufctl, istr, ilen, obuf, olen, flags, NULL);
1853 
1854 out:
1855     return ret;
1856 }
1857 
1858 /**
1859  * Converts a typed message buffer into an externalized JSON representation
1860  * @param ibuf typed message buffer
1861  * @param ilen specifies how much of ibuf to export
1862  * @param ostr pointer to the output JSON
1863  * @param olen input maximum available size, actual number of bytes written to ostr
1864  * @param flags 
1865  * @return 
1866  */
1867 extern int tpexport(char *ibuf, long ilen, char *ostr, long *olen, long flags)
1868 {
1869     int ret=EXSUCCEED;
1870     int entry_status=EXSUCCEED;
1871     API_ENTRY;
1872 
1873     if (EXSUCCEED!=entry_status)
1874     {
1875         EXFAIL_OUT(ret);
1876     }
1877 
1878     /* Check some other parameters */
1879     if (ibuf==NULL)
1880     {
1881         ndrx_TPset_error_msg(TPEINVAL, "ibuf cannot be null");
1882         EXFAIL_OUT(ret);
1883     }
1884 
1885     /* Check some other parameters */
1886     if (ostr==NULL)
1887     {
1888         ndrx_TPset_error_msg(TPEINVAL, "ostr cannot be null");
1889         EXFAIL_OUT(ret);
1890     }
1891     
1892     ret=ndrx_tpexportex(NULL, ibuf, ilen, ostr, olen, flags, NULL);
1893 
1894 out:
1895     return ret;
1896 }
1897 
1898 /**
1899  * Converts a typed message buffer into an externalized JSON representation
1900  * @param bufctl 
1901  * @param ibuf typed message buffer
1902  * @param ilen specifies how much of ibuf to export
1903  * @param ostr pointer to the output JSON
1904  * @param olen input maximum available size, actual number of bytes written to ostr
1905  * @param flags
1906  * @return 
1907  */
1908 extern int tpexportex(ndrx_expbufctl_t *bufctl, 
1909         char *ibuf, long ilen, char *ostr, long *olen, long flags)
1910 {
1911     int ret=EXSUCCEED;
1912     int entry_status=EXSUCCEED;
1913     API_ENTRY;
1914 
1915     if (EXSUCCEED!=entry_status)
1916     {
1917         EXFAIL_OUT(ret);
1918     }
1919 
1920    /* Check some other parameters */
1921     if (ibuf==NULL)
1922     {
1923         ndrx_TPset_error_msg(TPEINVAL, "ibuf cannot be null");
1924         EXFAIL_OUT(ret);
1925     }
1926 
1927     if (ostr==NULL)
1928     {
1929         ndrx_TPset_error_msg(TPEINVAL, "ostr cannot be null");
1930         EXFAIL_OUT(ret);
1931     }
1932 
1933     if (olen<=0)
1934     {
1935         ndrx_TPset_error_msg(TPEINVAL, "olen cannot be 0");
1936         EXFAIL_OUT(ret);
1937     }
1938 
1939     ret=ndrx_tpexportex(bufctl, ibuf, ilen, ostr, olen, flags, NULL);
1940 
1941 out:
1942     return ret;
1943 }
1944 
1945 /**
1946  * Read environment variable.
1947  * On unix it is the same as getenv()
1948  * @param envname env variable name
1949  * @return env variable value or NULL if not found
1950  */
1951 expublic char *tuxgetenv(char *envname)
1952 {
1953     return getenv(envname);
1954 }
1955 
1956 /**
1957  * Added for compatibility
1958  * @param flags ?
1959  * @return always FAIL
1960  */
1961 expublic int tperrordetail(long flags)
1962 {
1963     /* STUB function */
1964     return EXFAIL;
1965 }
1966 
1967 /**
1968  * Basically the same as tpstrerror - it always returns the last err msg
1969  * @param err ATMI error
1970  * @param flags RFU
1971  * @return error detail string
1972  */
1973 expublic char * tpstrerrordetail(int err, long flags)
1974 {
1975     return tpstrerror(err);
1976 }
1977 
1978 /**
1979  * User thread app init
1980  * Added for compatibility
1981  * @param tpthrinfo
1982  * @return EXSUCCEED/EXFAIL
1983  */
1984 expublic int tpappthrinit(TPINIT *tpinfo)
1985 {
1986     return tpinit(tpinfo);
1987 }
1988 
1989 /**
1990  * User thread terminate
1991  * Added for compatibility
1992  * @return EXSUCCEED/EXFAIL
1993  */
1994 expublic int tpappthrterm(void)
1995 {
1996     return tpterm();
1997 }
1998 
1999 /**
2000  * Get connection object of custom XA Switch
2001  * @return NULL in case of connection not open or no custom xa switch used
2002  *  otherwise it is ptr to connection object
2003  */
2004 expublic void* tpgetconn(void)
2005 {
2006     void *ptr = NULL;
2007     int entry_status=EXSUCCEED;
2008     API_ENTRY;
2009 
2010     if (EXSUCCEED!=entry_status)
2011     {
2012         goto out;
2013     }
2014     
2015     if (NULL==G_atmi_env.pf_getconn)
2016     {
2017         ndrx_TPset_error_msg(TPENOENT, "getconn callback is not set by driver");
2018     }
2019     
2020     ptr = G_atmi_env.pf_getconn();
2021     
2022 out:
2023     
2024     return ptr;
2025 }
2026 
2027 /**
2028  * Encrypt data block.
2029  * Currently AES-128 is used, CBC mode
2030  * In string mode (TPEX_STRING) - input is 0x0 terminated string, on output base64
2031  * encoded data (output buffer size is checked, but no len provided)
2032  * @param input input input data
2033  * @param ilen input string len (not used for TPEX_STRING)
2034  * @param output output buffer
2035  * @param olen output buffer len
2036  * @param flags TPEX_STRING - input & output data is string
2037  * @return EXSUCCEED/EXFAIL tperror loaded
2038  */
2039 expublic int tpencrypt(char *input, long ilen, char *output, long *olen, long flags)
2040 {
2041     int ret = EXSUCCEED;
2042     /* no API/Client init pls */
2043     ndrx_TPunset_error();
2044     
2045     if (NULL==input)
2046     {
2047         ndrx_TPset_error_msg(TPEINVAL, "input cannot be null");
2048         EXFAIL_OUT(ret);
2049     }
2050     
2051     if (NULL==output)
2052     {
2053         ndrx_TPset_error_msg(TPEINVAL, "output cannot be null");
2054         EXFAIL_OUT(ret);
2055     }
2056     
2057     if (NULL==olen)
2058     {
2059         ndrx_TPset_error_msg(TPEINVAL, "olen cannot be null");
2060         EXFAIL_OUT(ret);
2061     }
2062     
2063     if (!(flags & TPEX_STRING) && ilen <= 0)
2064     {
2065         ndrx_TPset_error_fmt(TPEINVAL, "Invalid ilen, expected data size len (%ld)>0", 
2066                 ilen);
2067         EXFAIL_OUT(ret);
2068     }
2069     
2070     ret=tpencrypt_int(input, ilen, output, olen, flags);
2071     
2072 out:
2073     return ret;
2074 }
2075 
2076 /**
2077  * Decrypt data block.
2078  * Currently AES-128 is used, CBC mode
2079  * In string mode (TPEX_STRING) - input is 0x0 terminated string with base64 data,
2080  * on output 0x0 terminate string is provided. No len is provided on output
2081  * but output buffer size is tested.
2082  * @param input input data buffer, string or binary data
2083  * @param ilen input len (only for binary)
2084  * @param output output buffer
2085  * @param olen output buffer size, on output len provided (only for binary mode)
2086  * @param flags TPEX_STRING - input & output data is string
2087  * @return EXSUCCEED/EXFAIL
2088  */
2089 expublic int tpdecrypt(char *input, long ilen, char *output, long *olen, long flags)
2090 {
2091     int ret = EXSUCCEED;
2092     /* no API/Client init pls */
2093     ndrx_TPunset_error();
2094     
2095     if (NULL==input)
2096     {
2097         ndrx_TPset_error_msg(TPEINVAL, "input cannot be null");
2098         EXFAIL_OUT(ret);
2099     }
2100     
2101     if (NULL==output)
2102     {
2103         ndrx_TPset_error_msg(TPEINVAL, "output cannot be null");
2104         EXFAIL_OUT(ret);
2105     }
2106     
2107     if (NULL==olen)
2108     {
2109         ndrx_TPset_error_msg(TPEINVAL, "olen cannot be null");
2110         EXFAIL_OUT(ret);
2111     }
2112     
2113     if (!(flags & TPEX_STRING) && ilen <= 0)
2114     {
2115         ndrx_TPset_error_fmt(TPEINVAL, "Invalid ilen, expected data size len (%ld)>0", 
2116                 ilen);
2117         EXFAIL_OUT(ret);
2118     }
2119     
2120     ret=tpdecrypt_int(input, ilen, output, olen, flags);
2121     
2122 out:
2123     return ret;
2124 }
2125 
2126 /**
2127  * Set next call priority.
2128  * This affects
2129  * - tpcall, tpacall, tpconnect, tpforward, tpnotify
2130  * - for tpbroadcast only first matched recipient will be approached with this
2131  *   priority.
2132  * Default is 50
2133  * 
2134  * @param prio priority 1..100
2135  * @param flags TPABSOLUTE (ignored)
2136  * @return 
2137  */
2138 expublic int tpsprio(int prio, long flags)
2139 {
2140     int ret=EXSUCCEED;
2141     ndrx_TPunset_error();
2142     
2143     if ( (flags & ~TPABSOLUTE) !=0 )
2144     {
2145         ndrx_TPset_error_fmt(TPEINVAL, "Unsupported flags %ld", flags);
2146         EXFAIL_OUT(ret);
2147     }
2148     
2149     if (flags & TPABSOLUTE )
2150     {
2151         if (prio < NDRX_MSGPRIO_MIN || prio >NDRX_MSGPRIO_MAX)
2152         {
2153             ndrx_TPset_error_fmt(TPEINVAL, "prio must be in range %d..%d, got %d", 
2154                     NDRX_MSGPRIO_MIN, NDRX_MSGPRIO_MAX, prio);
2155             EXFAIL_OUT(ret);
2156         }
2157     }
2158     else
2159     {
2160         if (abs(prio) > NDRX_MSGPRIO_MAX)
2161         {
2162             ndrx_TPset_error_fmt(TPEINVAL, "Invalid relative prio, ABS value "
2163                     "shall be less than or equal to %d", prio,
2164                     NDRX_MSGPRIO_MAX);
2165             EXFAIL_OUT(ret);
2166         }
2167     }
2168     
2169     G_atmi_tls->prio = prio;
2170     G_atmi_tls->prio_flags = flags;
2171     
2172     NDRX_LOG(log_debug, "Next call scheduled with priority %d flags %ld",  
2173             G_atmi_tls->prio, G_atmi_tls->prio_flags);
2174 
2175 out:
2176     return ret;
2177 }
2178 
2179 /**
2180  * Get priority of the last call
2181  * If call was not made, default value 50 is returned.
2182  * @return priority 1..100
2183  */
2184 expublic int tpgprio(void)
2185 {
2186     ndrx_TPunset_error();
2187     return G_atmi_tls->prio_last;
2188 }
2189 
2190 /**
2191  * Set block time.
2192  * @param blktime time in seconds. Value 0 disables such setting.
2193  * @param flags flags TPBLK_NEXT or TPBLK_ALL
2194  * @return 0 on succeed, -1 on error
2195  */
2196 expublic int tpsblktime(int tout,long flags)
2197 {
2198     int ret = EXSUCCEED;
2199     
2200     ndrx_TPunset_error();
2201     
2202     /* validate flags */
2203     if ( flags & (~ ((long) TPBLK__MASK)))
2204     {
2205         NDRX_LOG(log_error, "Invalid flags 0x%x", flags);
2206         ndrx_TPset_error_fmt(TPEINVAL, "Invalid flags 0x%x",
2207                 flags);
2208         EXFAIL_OUT(ret);
2209     }
2210     
2211     if (tout < 0)
2212     {
2213         NDRX_LOG(log_error, "Invalid blktime %d", tout);
2214         ndrx_TPset_error_fmt(TPEINVAL, "Invalid blktime %d", tout);
2215         EXFAIL_OUT(ret);
2216     }
2217     
2218     if (TPBLK_NEXT & flags)
2219     {
2220         /* set value for next */
2221         
2222         if (0==tout)
2223         {
2224             G_atmi_tls->tout_next = EXFAIL;
2225             NDRX_LOG(log_debug, "Thread next tout disabled");
2226         }
2227         else
2228         {
2229             G_atmi_tls->tout_next = tout;
2230             NDRX_LOG(log_debug, "Thread next tout call set to %d", G_atmi_tls->tout_next);
2231         }
2232     }
2233     
2234     if (TPBLK_ALL & flags)
2235     {
2236         if (0==tout)
2237         {
2238             G_atmi_tls->tout = EXFAIL;
2239             NDRX_LOG(log_debug, "Thread specific tout disabled");
2240         }
2241         else
2242         {
2243             G_atmi_tls->tout = tout;
2244             NDRX_LOG(log_debug, "Thread specific tout set to %d", G_atmi_tls->tout);
2245         }
2246     }
2247 out:
2248     return ret;
2249 }
2250 
2251 /**
2252  * Get timeout value. If particular setting is not set, 0 return next blocking
2253  *  call timeout value, either next,all or system wide.
2254  * @param flags
2255  * @return 
2256  */
2257 expublic int tpgblktime(long flags)
2258 {
2259     int ret = EXSUCCEED;
2260     
2261     ndrx_TPunset_error();
2262     
2263     /* validate flags */
2264     if ( flags & (~ ((long) TPBLK__MASK)))
2265     {
2266         ndrx_TPset_error_fmt(TPEINVAL, "Invalid flags 0x%x",
2267                 flags);
2268         EXFAIL_OUT(ret);
2269     }
2270     
2271     if ((flags & TPBLK_NEXT) &&  (flags & TPBLK_ALL))
2272     {
2273         ndrx_TPset_error_fmt(TPEINVAL, "Flags 0x%x shall TPBLK_NEXT or TPBLK_ALL",
2274                 flags);
2275         EXFAIL_OUT(ret);
2276     }
2277     
2278     if (flags & TPBLK_NEXT)
2279     {
2280         if (EXFAIL!=G_atmi_tls->tout_next)
2281         {
2282             ret = G_atmi_tls->tout_next;
2283         }
2284     }
2285     else if (flags & TPBLK_ALL)
2286     {
2287         if (EXFAIL!=G_atmi_tls->tout)
2288         {
2289             ret = G_atmi_tls->tout;
2290         }
2291     }
2292     else
2293     {
2294         /* Next effective timeout */
2295         if (EXFAIL!=G_atmi_tls->tout_next)
2296         {
2297             /* as yet to be applied to effective */
2298             ret = G_atmi_tls->tout_next;
2299         }
2300         else
2301         {
2302             ret = ndrx_tptoutget_eff();
2303         }
2304         
2305         if (EXFAIL==ret)
2306         {
2307             /* set the error */
2308             ndrx_TPset_error_fmt(TPESYSTEM, "Init was not called");
2309         }
2310     }
2311     
2312 out:
2313     NDRX_LOG(log_debug, "flags 0x%x ret %d", flags, ret);
2314     return ret;
2315 }
2316 
2317 /**
2318  * Check is given singleton process group locked.
2319  * @param grpno singleton group number
2320  * @param flags TPACK
2321  * @arpam grp_flags group flags (output)
2322  * @return EXAIL/EXFALSE/>0 locked, seqno
2323  */
2324 expublic long tpsgislocked(int grpno, long flags, long *grp_flags)
2325 {
2326     long ret = EXSUCCEED;
2327     
2328     ndrx_TPunset_error();
2329     
2330      if ( (flags & ~ (TPPG_SGVERIFY|TPPG_NONSGSUCC)) !=0 )
2331     {
2332         ndrx_TPset_error_fmt(TPEINVAL, "Unsupported flags %ld", flags);
2333         EXFAIL_OUT(ret);
2334     }
2335 
2336     ret = ndrx_tpsgislocked(grpno, flags, grp_flags);
2337 
2338 out:
2339     return ret;
2340 }
2341 
2342 /* vim: set ts=4 sw=4 et smartindent: */