Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief CARRAY buffer support
0003  *
0004  * @file typed_carray.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 <errno.h>
0039 #include <utlist.h>
0040 
0041 #include <tperror.h>
0042 #include <ubf.h>
0043 #include <atmi.h>
0044 #include <typed_buf.h>
0045 #include <ndebug.h>
0046 #include <fdatatype.h>
0047 #include <userlog.h>
0048 #include <typed_carray.h>
0049 /*---------------------------Externs------------------------------------*/
0050 /*---------------------------Macros-------------------------------------*/
0051 #define CARRAY_DEFAULT_SIZE    512
0052 /*---------------------------Enums--------------------------------------*/
0053 /*---------------------------Typedefs-----------------------------------*/
0054 /*---------------------------Globals------------------------------------*/
0055 /*---------------------------Statics------------------------------------*/
0056 /*---------------------------Prototypes---------------------------------*/
0057 /*
0058  * Prepare buffer for outgoing call/reply
0059  * idata - buffer data
0060  * ilen - data len (if needed)
0061  * obuf - place where to copy prepared buffer
0062  * olen - the actual lenght of data that should sent. Also this may represent
0063  *          space for the buffer to copy to.
0064  */
0065 expublic int CARRAY_prepare_outgoing (typed_buffer_descr_t *descr, char *idata, long ilen, 
0066                     char *obuf, long *olen, long flags)
0067 {
0068     int ret=EXSUCCEED;
0069     char fn[]="CARRAY_prepare_outgoing";
0070     
0071     /* Check that we have space enough to prepare for send */
0072     if (NULL!=olen && *olen < ilen)
0073     {
0074         ndrx_TPset_error_fmt(TPEINVAL, "%s: Internal buffer space: %d, "
0075                 "but requested: %d", fn, *olen, ilen);
0076         ret=EXFAIL;
0077         goto out;
0078     }
0079 
0080     memcpy(obuf, idata, ilen);
0081     
0082     /* return the actual length! */
0083     if (NULL!=olen)
0084         *olen = ilen;
0085     
0086 out:
0087     return ret;
0088 }
0089 
0090 /*
0091  * Prepare received buffer for internal processing.
0092  * May re-allocate the buffer.
0093  * rcv_data - received data buffer
0094  * odata - ptr to handler. Existing buffer may be reused or re-allocated
0095  * olen - output data length
0096  */
0097 expublic int CARRAY_prepare_incoming (typed_buffer_descr_t *descr, char *rcv_data, 
0098                         long rcv_len, char **odata, long *olen, long flags)
0099 {
0100     int ret=EXSUCCEED;
0101     int rcv_buf_size;
0102     int existing_size;
0103     
0104     char fn[]="CARRAY_prepare_incoming";
0105     buffer_obj_t *outbufobj=NULL;
0106 
0107     NDRX_LOG(log_debug, "Entering %s", fn);
0108     
0109     rcv_buf_size = rcv_len;
0110    
0111     
0112     /* Figure out the passed in buffer */
0113     if (NULL==(outbufobj=ndrx_find_buffer(*odata)))
0114     {
0115         ndrx_TPset_error_fmt(TPEINVAL, "Output buffer %p is not allocated "
0116                                         "with tpalloc()!", *odata);
0117         ret=EXFAIL;
0118         goto out;
0119     }
0120 
0121     /* Check the data types */
0122     if (NULL!=outbufobj)
0123     {
0124         /* If we cannot change the data type, then we trigger an error */
0125         if (flags & TPNOCHANGE && outbufobj->type_id!=BUF_TYPE_CARRAY)
0126         {
0127             /* Raise error! */
0128             ndrx_TPset_error_fmt(TPEOTYPE, "Receiver expects %s but got %s buffer",
0129                                         G_buf_descr[BUF_TYPE_NULL].type,
0130                                         G_buf_descr[outbufobj->type_id].type
0131                                         );
0132             ret=EXFAIL;
0133             goto out;
0134         }
0135         /* If we can change data type and this does not match, then
0136          * we should firstly free it up and then bellow allow to work in mode
0137          * when odata is NULL!
0138          */
0139         if (outbufobj->type_id!=BUF_TYPE_CARRAY)
0140         {
0141             NDRX_LOG(log_warn, "User buffer %s is different, "
0142                     "free it up and re-allocate as CARRAY", G_buf_descr[outbufobj->type_id].type);
0143             ndrx_tpfree(*odata, outbufobj);
0144             *odata=NULL;
0145         }
0146     }
0147     
0148     /* check the output buffer */
0149     if (NULL!=*odata)
0150     {
0151         NDRX_LOG(log_debug, "%s: Output buffer exists", fn);
0152         
0153         existing_size = outbufobj->size;
0154         
0155 
0156         NDRX_LOG(log_debug, "%s: Output buffer size: %d, received %d", fn,
0157                             existing_size, rcv_buf_size);
0158         
0159         if (existing_size>=rcv_buf_size)
0160         {
0161             /* re-use existing buffer */
0162             NDRX_LOG(log_debug, "%s: Using existing buffer", fn);
0163         }
0164         else
0165         {
0166             /* Reallocate the buffer, because we have missing some space */
0167             char *new_addr;
0168             NDRX_LOG(log_debug, "%s: Reallocating", fn);
0169             
0170             if (NULL==(new_addr=ndrx_tprealloc(*odata, rcv_buf_size)))
0171             {
0172                 NDRX_LOG(log_error, "%s: _tprealloc failed!", fn);
0173                 ret=EXFAIL;
0174                 goto out;
0175             }
0176 
0177             /* allocated OK, return new address */
0178             *odata = new_addr;
0179         }
0180     }
0181     else
0182     {
0183         /* allocate the buffer */
0184         NDRX_LOG(log_debug, "%s: Incoming buffer where missing - "
0185                                          "allocating new!", fn);
0186 
0187         *odata = ndrx_tpalloc(&G_buf_descr[BUF_TYPE_CARRAY], NULL, NULL, rcv_len);
0188 
0189         if (NULL==*odata)
0190         {
0191             /* error should be set already */
0192             NDRX_LOG(log_error, "Failed to allocat new buffer!");
0193             goto out;
0194         }
0195     }
0196     
0197     /* Copy off the received data including EOS ofcorse. */
0198     memcpy(*odata, rcv_data, rcv_len);
0199 
0200     if (NULL!=olen)
0201     {
0202         *olen = rcv_len;
0203     }
0204     
0205 out:
0206     return ret;
0207 }
0208 
0209 /**
0210  * Allocate the buffer & register this into list, that we have such
0211  * List maintenance should be done by parent process tpalloc!
0212  * @param subtype
0213  * @param len
0214  * @return
0215  */
0216 expublic char * CARRAY_tpalloc (typed_buffer_descr_t *descr, char *subtype, long *len)
0217 {
0218     char *ret;
0219 
0220     if (CARRAY_DEFAULT_SIZE > *len )
0221     {
0222         *len = CARRAY_DEFAULT_SIZE;
0223     }
0224 
0225     /* Allocate CARRAY buffer */
0226     ret=(char *)NDRX_MALLOC(*len);
0227     
0228     if (NULL!=ret)
0229     {
0230         ret[0] = EXEOS;
0231     }
0232     else
0233     {
0234         ndrx_TPset_error_fmt(TPEOS, "%s: Failed to allocate CARRAY buffer (len=%ld): %s",  
0235                 __func__, len, strerror(errno));
0236     }
0237     
0238 out:
0239     return ret;
0240 }
0241 
0242 /**
0243  * Re-allocate CARRAY buffer. Firstly we will find it in the list.
0244  * @param ptr
0245  * @param size
0246  * @return
0247  */
0248 expublic char * CARRAY_tprealloc(typed_buffer_descr_t *descr, char *cur_ptr, long len)
0249 {
0250     char *ret=NULL;
0251     
0252     if (0==len)
0253     {
0254         len = CARRAY_DEFAULT_SIZE;
0255     }
0256 
0257     /* Allocate CARRAY buffer */
0258     ret=(char *)NDRX_REALLOC(cur_ptr, len);
0259     
0260     if (NULL==ret)
0261     {
0262         ndrx_TPset_error_fmt(TPEOS, "%s: Failed to reallocate CARRAY buffer (len=%ld): %s",  
0263                 __func__, len, strerror(errno));
0264     }
0265 
0266     return ret;
0267 }
0268 
0269 /**
0270  * Gracefully remove free up the buffer
0271  * @param descr
0272  * @param buf
0273  */
0274 expublic void CARRAY_tpfree(typed_buffer_descr_t *descr, char *buf)
0275 {
0276     NDRX_FREE(buf);
0277 }
0278 
0279 /**
0280  * Check the expression on buffer.
0281  * @param descr
0282  * @param buf
0283  * @param expr
0284  * @return TRUE/FALSE.
0285  * In case of error we just return FALSE as not matched!
0286  */
0287 expublic int CARRAY_test(typed_buffer_descr_t *descr, char *buf, BFLDLEN len, char *expr)
0288 {
0289     int ret=EXFALSE;
0290 
0291     NDRX_LOG(log_error, "Carray buffers do not support event filters! Expr: [%s]", expr);
0292     userlog("Carray buffers do not support event filters! Expr: [%s]", expr);
0293     
0294     return ret;
0295 }
0296 
0297 
0298 /* vim: set ts=4 sw=4 et smartindent: */