Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief ATMI cache management routines
0003  *
0004  * @file atmi_cache_mgt.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 
0035 /*---------------------------Includes-----------------------------------*/
0036 #include <stdlib.h>
0037 #include <stdio.h>
0038 #include <errno.h>
0039 #include <string.h>
0040 #include <ndrstandard.h>
0041 #include <atmi.h>
0042 #include <atmi_tls.h>
0043 #include <typed_buf.h>
0044 
0045 #include "thlock.h"
0046 #include "userlog.h"
0047 #include "utlist.h"
0048 #include "exregex.h"
0049 #include <exparson.h>
0050 #include <atmi_cache.h>
0051 #include <Exfields.h>
0052 #include <ubfutil.h>
0053 /*---------------------------Externs------------------------------------*/
0054 /*---------------------------Macros-------------------------------------*/
0055 #define OFSZ(s,e)   EXOFFSET(s,e), EXELEM_SIZE(s,e)
0056 /*---------------------------Enums--------------------------------------*/
0057 /*---------------------------Typedefs-----------------------------------*/
0058 /*---------------------------Globals------------------------------------*/
0059 /*---------------------------Statics------------------------------------*/
0060 
0061 
0062 /**
0063  * Cache data mapping structure to UBF buffer
0064  */
0065 static ubf_c_map_t M_cachedata_map[] = 
0066 {
0067     {EX_CACHE_TPERRNO,  0, OFSZ(ndrx_tpcache_data_t, saved_tperrno),  BFLD_INT}, /* 0 */
0068     {EX_CACHE_TPRUCODE, 0, OFSZ(ndrx_tpcache_data_t, saved_tpurcode), BFLD_LONG}, /* 1 */
0069     {EX_CACHE_TIM,      0, OFSZ(ndrx_tpcache_data_t, t),              BFLD_LONG}, /* 2 */
0070     {EX_CACHE_TIMUSEC,  0, OFSZ(ndrx_tpcache_data_t, tusec),          BFLD_LONG}, /* 3 */
0071     {EX_CACHE_HITT,     0, OFSZ(ndrx_tpcache_data_t, hit_t),          BFLD_LONG}, /* 4 */
0072     {EX_CACHE_HITTU,    0, OFSZ(ndrx_tpcache_data_t, hit_tusec),      BFLD_LONG}, /* 5 */
0073     {EX_CACHE_HITS,     0, OFSZ(ndrx_tpcache_data_t, hits),           BFLD_LONG}, /* 6 */
0074     {EX_CACHE_NODEID,   0, OFSZ(ndrx_tpcache_data_t, nodeid),         BFLD_SHORT}, /* 7 */
0075     {EX_CACHE_BUFTYP,   0, OFSZ(ndrx_tpcache_data_t, atmi_type_id),   BFLD_SHORT}, /* 8 */
0076     {EX_CACHE_BUFLEN,   0, OFSZ(ndrx_tpcache_data_t, atmi_buf_len),   BFLD_LONG}, /* 9 */    
0077     {BBADFLDID}
0078 };
0079 
0080 /**
0081  * Cache data exchange optionality - all required.
0082  */
0083 static long M_cachedata_req[] = 
0084 {
0085     UBFUTIL_EXPORT,/* 0 */
0086     UBFUTIL_EXPORT,/* 1 */
0087     UBFUTIL_EXPORT,/* 2 */
0088     UBFUTIL_EXPORT,/* 3 */
0089     UBFUTIL_EXPORT,/* 4 */
0090     UBFUTIL_EXPORT,/* 5 */
0091     UBFUTIL_EXPORT,/* 6 */
0092     UBFUTIL_EXPORT,/* 7 */
0093     UBFUTIL_EXPORT,/* 8 */
0094     UBFUTIL_EXPORT /* 9 */
0095 };
0096 
0097 /*---------------------------Prototypes---------------------------------*/
0098 
0099 /**
0100  * Return Management service name
0101  * @return static char buffer
0102  */
0103 expublic char* ndrx_cache_mgt_getsvc(void)
0104 {
0105     static char svcnm[XATMI_SERVICE_NAME_LENGTH+1];
0106     
0107     snprintf(svcnm, sizeof(svcnm), NDRX_CACHE_MGSVC, tpgetnodeid());
0108     
0109     return svcnm;
0110 }
0111 
0112 /**
0113  * Convert data to UBF
0114  * @param cdata data to convert
0115  * @param pp_ub double ptr to UBF, will be reallocated to get some space
0116  * @param incl_blob if !=0, then data will be loaded to UBF
0117  * @return EXSUCCEED/EXFAIL
0118  */
0119 expublic int ndrx_cache_mgt_data2ubf(ndrx_tpcache_data_t *cdata, char *keydata,
0120         UBFH **pp_ub, int incl_blob)
0121 {
0122     int ret = EXSUCCEED;
0123     int new_size;
0124     
0125     /* Remove any existing fields (may be left from previous run) */
0126     Bdel(*pp_ub, EX_CACHE_TPERRNO, 0);
0127     Bdel(*pp_ub, EX_CACHE_TPRUCODE, 0);
0128     Bdel(*pp_ub, EX_CACHE_TIM, 0);
0129     Bdel(*pp_ub, EX_CACHE_TIMUSEC, 0);
0130     Bdel(*pp_ub, EX_CACHE_HITT, 0);
0131     Bdel(*pp_ub, EX_CACHE_TIMUSEC, 0);
0132     Bdel(*pp_ub, EX_CACHE_HITS, 0);
0133     Bdel(*pp_ub, EX_CACHE_NODEID, 0);
0134     Bdel(*pp_ub, EX_CACHE_BUFTYP, 0);
0135     
0136     /* Get some 1K free */
0137     
0138     new_size=Bused(*pp_ub) + strlen(keydata) + 1024;
0139     
0140     *pp_ub = (UBFH *)tprealloc((char *)*pp_ub, new_size);
0141     
0142     if (NULL==*pp_ub)
0143     {
0144         NDRX_LOG(log_error, "Failed to reallocate new buffer size: %ld", new_size);
0145         EXFAIL_OUT(ret);
0146     }
0147     
0148     NDRX_LOG(log_debug, "tusec=%ld", cdata->tusec);
0149     
0150     if (EXSUCCEED!=(ret=atmi_cvt_c_to_ubf(M_cachedata_map, cdata, 
0151             *pp_ub, M_cachedata_req)))
0152     {
0153         NDRX_LOG(log_error, "%s: failed to convert data to UBF", __func__);
0154         NDRX_TPCACHETPCALL_DBDATA(log_debug, cdata);
0155         
0156         EXFAIL_OUT(ret);
0157     }
0158     
0159     /* Load they key */
0160     
0161     if (EXSUCCEED!=Bchg(*pp_ub, EX_CACHE_OPEXPR, 0, (char *)keydata, 0L))
0162     {
0163         NDRX_LOG(log_error, "Failed to set EX_CACHE_OPEXPR field: %s", 
0164                     Bstrerror(Berror));
0165         EXFAIL_OUT(ret);
0166     }
0167     
0168     /* if putting blob, then even more we need. */
0169     
0170     if (incl_blob)
0171     {
0172         /* Have a bit over for TLV. */
0173         new_size=Bused(*pp_ub)+cdata->atmi_buf_len+256;
0174 
0175         *pp_ub = (UBFH *)tprealloc((char *)*pp_ub, new_size);
0176 
0177         if (NULL==*pp_ub)
0178         {
0179             NDRX_LOG(log_error, "Failed to reallocate new buffer size: %ld", 
0180                     new_size);
0181             EXFAIL_OUT(ret);
0182         }
0183         
0184         if (EXSUCCEED!=Bchg(*pp_ub, EX_CACHE_DUMP, 0, cdata->atmi_buf, 
0185                 cdata->atmi_buf_len))
0186         {
0187             NDRX_LOG(log_error, "Failed to set EX_CACHE_DUMP field: %s", 
0188                     Bstrerror(Berror));
0189             EXFAIL_OUT(ret);
0190         }
0191     }
0192     
0193 out:
0194     return ret;
0195 }
0196 
0197 
0198 /**
0199  * Convert UBF to data structure. The blob will be loaded separately in allocated
0200  * space.
0201  * @param pp_ub UBF will EX_CACHE* fields
0202  * @param cdata output struct where to load the incoming data
0203  * @param data ptr to space where to allocate the incoming blob (if present in UBF)
0204  * @param odata if not NULL, this is output incoming data (XATMI buffer)
0205  * @param 
0206  * @return EXSUCCEED/EXFAIL
0207  */
0208 expublic int ndrx_cache_mgt_ubf2data(UBFH *p_ub, ndrx_tpcache_data_t *cdata, 
0209         char **blob, char **keydata, char **odata, long *olen)
0210 {
0211     int ret = EXSUCCEED;
0212     BFLDLEN len;
0213     
0214     if (EXSUCCEED!=atmi_cvt_ubf_to_c(M_cachedata_map, p_ub, cdata, M_cachedata_req))
0215     {
0216         NDRX_LOG(log_error, "Failed to convert ubf to tpcache_data");
0217         EXFAIL_OUT(ret);
0218     }
0219     
0220     /* Load the blob if present and data is set */
0221     
0222     if (NULL!=blob)
0223     {
0224         if (0>(len = Blen(p_ub, EX_CACHE_DUMP, 0)))
0225         {
0226             NDRX_LOG(log_error, "Failed to estimate EX_CACHE_DUMP size: %s", 
0227                     Bstrerror(Berror));
0228             EXFAIL_OUT(ret);
0229         }
0230         
0231         NDRX_MALLOC_OUT(*blob, len, char);
0232         
0233         /* hmm we need to get some statistics about the field */
0234         if (EXSUCCEED!=Bget(p_ub, EX_CACHE_DUMP, 0, *blob, &len))
0235         {
0236             NDRX_LOG(log_error, "Failed to get cache data: %s", Bstrerror(Berror));
0237             EXFAIL_OUT(ret);
0238         }
0239         
0240         if (cdata->atmi_buf_len != len)
0241         {
0242             NDRX_LOG(log_error, "ERROR ! real data len: %d, but "
0243                     "EX_CACHE_BUFLEN says: %ld",
0244                     len, cdata->atmi_buf_len);
0245             EXFAIL_OUT(ret);
0246         }
0247         
0248         /* TODO: what shall we do with FLD_PTR? */
0249         /* prepare incoming data if ptr present */
0250         if (EXSUCCEED!=ndrx_mbuf_prepare_incoming(*blob, 
0251             len, odata, olen, 0, 0))
0252         {
0253             /* the error shall be set already */
0254             NDRX_LOG(log_error, "Failed to prepare incoming buffer");
0255             EXFAIL_OUT(ret);
0256         }
0257         
0258     }
0259     
0260     if (NULL!=keydata)
0261     {
0262         if (0>(len = Blen(p_ub, EX_CACHE_OPEXPR, 0)))
0263         {
0264             NDRX_LOG(log_error, "Failed to estimate EX_CACHE_OPEXPR size: %s", 
0265                     Bstrerror(Berror));
0266         }
0267         
0268         NDRX_MALLOC_OUT(*keydata, len, char);
0269         
0270         if (EXSUCCEED!=Bget(p_ub, EX_CACHE_OPEXPR, 0, *keydata, &len))
0271         {
0272             NDRX_LOG(log_error, "Failed to get key data: %s", Bstrerror(Berror));
0273             EXFAIL_OUT(ret);
0274         }
0275     }
0276     
0277 out:
0278 
0279     if (EXSUCCEED!=ret)
0280     {
0281         if (NULL!=blob && *blob!=NULL)
0282         {
0283             NDRX_FREE(*blob);
0284             *keydata=NULL;
0285         }
0286         
0287         if (NULL!=keydata && *keydata!=NULL)
0288         {
0289             NDRX_FREE(*keydata);
0290             *keydata=NULL;
0291         }
0292     }
0293     return ret;
0294 }
0295 /* vim: set ts=4 sw=4 et smartindent: */