Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief UBF library
0003  *   This file implements find functions.
0004  *
0005  * @file find_impl.c
0006  */
0007 /* -----------------------------------------------------------------------------
0008  * Enduro/X Middleware Platform for Distributed Transaction Processing
0009  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0010  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0011  * This software is released under one of the following licenses:
0012  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0013  * See LICENSE file for full text.
0014  * -----------------------------------------------------------------------------
0015  * AGPL license:
0016  *
0017  * This program is free software; you can redistribute it and/or modify it under
0018  * the terms of the GNU Affero General Public License, version 3 as published
0019  * by the Free Software Foundation;
0020  *
0021  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0022  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0023  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0024  * for more details.
0025  *
0026  * You should have received a copy of the GNU Affero General Public License along 
0027  * with this program; if not, write to the Free Software Foundation, Inc.,
0028  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0029  *
0030  * -----------------------------------------------------------------------------
0031  * A commercial use license is available from Mavimax, Ltd
0032  * contact@mavimax.com
0033  * -----------------------------------------------------------------------------
0034  */
0035 
0036 /*---------------------------Includes-----------------------------------*/
0037 #include <stdio.h>
0038 #include <stdlib.h>
0039 #include <string.h>
0040 #include <stdio.h>
0041 #include <stdlib.h>
0042 #include <memory.h>
0043 
0044 #include <ubf.h>
0045 #include <ubf_int.h>    /* Internal headers for UBF... */
0046 #include <fdatatype.h>
0047 #include <ferror.h>
0048 #include <fieldtable.h>
0049 #include <ndrstandard.h>
0050 #include <ndebug.h>
0051 #include <cf.h>
0052 
0053 #include "ubf_tls.h"
0054 /*---------------------------Externs------------------------------------*/
0055 /*---------------------------Macros-------------------------------------*/
0056 /*---------------------------Enums--------------------------------------*/
0057 /*---------------------------Typedefs-----------------------------------*/
0058 /*---------------------------Globals------------------------------------*/
0059 /*---------------------------Statics------------------------------------*/
0060 /*---------------------------Prototypes---------------------------------*/
0061 
0062 /**
0063  * Find the entry into buffer.
0064  * Return raw pointer directly
0065  * @param p_ub
0066  * @param bfldid
0067  * @param occ
0068  * @param p_len
0069  * @param p_fld - pointer to start of the actual field (optional)
0070  * @return
0071  */
0072 expublic char * ndrx_Bfind (UBFH * p_ub, BFLDID bfldid,
0073                                         BFLDOCC occ, BFLDLEN * len,
0074                                         char **p_fld)
0075 {
0076     dtype_str_t *dtype;
0077     char *last_checked=NULL;
0078     int last_occ;
0079     char *ret = NULL;
0080     int data_len = 0;
0081     dtype_ext1_t *dtype_ext1;
0082     char fn[] = "_Bfind";
0083 /***************************************** DEBUG *******************************/
0084     #ifdef UBF_API_DEBUG
0085     dtype_ext1_t *__dbg_dtype_ext1;
0086     #endif
0087 /*******************************************************************************/
0088 
0089     UBF_LOG(log_debug, "Bfind: bfldid: %d occ: %hd", bfldid, occ);
0090 
0091     if (UBF_BINARY_SEARCH_OK(bfldid))
0092     {
0093         ret=get_fld_loc_binary_search(p_ub, bfldid, occ, &dtype, 
0094                 UBF_BINSRCH_GET_LAST_NONE, NULL, NULL, NULL);
0095     }
0096     else
0097     {
0098         ret=get_fld_loc(p_ub, bfldid, occ,
0099                                 &dtype,
0100                                 &last_checked,
0101                                 NULL,
0102                                 &last_occ,
0103                                 NULL);
0104     }
0105 
0106     /* Get the data size of Bfind */
0107     if (NULL!=ret)
0108     {
0109         int dlen;
0110 
0111         /* Save the pointer to the field */
0112         if (NULL!=p_fld)
0113         {
0114             *p_fld=ret;
0115         }
0116 
0117         /* Get the payload size */
0118         if (NULL!=len)
0119         {
0120            /* *len = data_len;*/
0121            dtype->p_next(dtype, (char *)ret, len);
0122         }
0123 
0124         dtype_ext1 = &G_dtype_ext1_map[dtype->fld_type];
0125         dlen = dtype_ext1->hdr_size;
0126         
0127         if (NULL!=dtype_ext1->p_prep_ubfp)
0128         {
0129             /* translate to value */
0130             ret=dtype_ext1->p_prep_ubfp(dtype_ext1, 
0131                     &G_ubf_tls->ndrx_Bfind_tls_stor, ret);
0132         }
0133         else
0134         {
0135             /* Move us to start of the data. */
0136             ret+=dlen;
0137         }
0138     }
0139     else
0140     {
0141         UBF_LOG(log_debug, "%s: Field not present!", fn);
0142         ndrx_Bset_error(BNOTPRES);
0143     }
0144 
0145     UBF_LOG(log_debug, "Bfind: return: %p", ret);
0146 /***************************************** DEBUG *******************************/
0147     #ifdef UBF_API_DEBUG
0148     if (NULL!=ret)
0149     {
0150         __dbg_dtype_ext1 = &G_dtype_ext1_map[bfldid>>EFFECTIVE_BITS];
0151         __dbg_dtype_ext1->p_dump_data(__dbg_dtype_ext1, "_Bfind got data", ret, len);
0152     }
0153     #endif
0154 /*******************************************************************************/
0155     return ret;
0156 }
0157 
0158 /**
0159  * Internal version of CBFind.
0160  * @param p_ub
0161  * @param bfldid
0162  * @param occ
0163  * @param buf
0164  * @param type
0165  * @return
0166  */
0167 expublic char * ndrx_CBfind (UBFH *p_ub, BFLDID bfldid,
0168                         BFLDOCC occ, BFLDLEN * len, int usrtype,
0169                         int mode, int extralen)
0170 {
0171     int from_type = (bfldid>>EFFECTIVE_BITS);
0172     BFLDLEN tmp_len = 0;
0173     char *cvn_buf;
0174     char *fb_data;
0175     char *alloc_buf=NULL;
0176     int alloc_size = 0;
0177     char *ret=NULL;
0178 /***************************************** DEBUG *******************************/
0179     #ifdef UBF_API_DEBUG
0180     dtype_ext1_t *__dbg_dtype_ext1 = &G_dtype_ext1_map[usrtype];
0181     #endif
0182 /*******************************************************************************/
0183 
0184     fb_data=ndrx_Bfind (p_ub, bfldid, occ, &tmp_len, NULL);
0185 
0186     if (NULL!=fb_data)
0187     {
0188         /* Allocate the buffer */
0189         if (NULL==(cvn_buf=ndrx_ubf_get_cbuf(from_type, usrtype,
0190                         NULL, fb_data, tmp_len,
0191                         &alloc_buf,
0192                         &alloc_size,
0193                         mode,
0194                         extralen)))
0195         {
0196             UBF_LOG(log_error, "%s: get_cbuf failed!", __func__);
0197             ndrx_Bset_error_fmt(BEUNIX, "%s: get_cbuf failed!", __func__);
0198             /* Error should be already set */
0199             return NULL; /* <<<< RETURN!!!! */
0200         }
0201         
0202         /* Bug #330*/
0203         if (NULL!=len)
0204         {
0205             *len = alloc_size;
0206         }
0207         
0208         ret = ndrx_ubf_convert(from_type, CNV_DIR_OUT, fb_data, tmp_len,
0209                                     usrtype, cvn_buf, len);
0210         if (NULL==ret)
0211         {
0212             UBF_LOG(log_error, "%s: failed to convert data!", __func__);
0213             ndrx_Bset_error_fmt(BEUNIX, "%s: failed to convert data!", __func__);
0214             /* Error should be provided by conversation function */
0215             ret=NULL;
0216         }
0217     }
0218     else
0219     {
0220         UBF_LOG(log_error, "%s: Field not present!", __func__);
0221         ret=NULL;
0222     }
0223 /***************************************** DEBUG *******************************/
0224     #ifdef UBF_API_DEBUG
0225     if (NULL!=ret)
0226     {
0227         __dbg_dtype_ext1->p_dump_data(__dbg_dtype_ext1, "_CBfind got data", ret, len);
0228     }
0229     #endif
0230 /*******************************************************************************/
0231     return ret;
0232 }
0233 
0234 /**
0235  * Internal Bfindocc implementation.
0236  * @param p_ub
0237  * @param bfldid
0238  * @param value
0239  * @param len
0240  * @return
0241  */
0242 expublic BFLDOCC ndrx_Bfindocc (UBFH *p_ub, BFLDID bfldid, char * buf, BFLDLEN len)
0243 {
0244     dtype_str_t *dtype=NULL;
0245     dtype_ext1_t *dtype_ext1;
0246     UBF_header_t *hdr = (UBF_header_t *)p_ub;
0247     char *last_checked=NULL;
0248     int last_occ;
0249     BFLDOCC ret = EXFAIL;
0250     char *fn = "_Bfindocc";
0251     BFLDLEN dlen;
0252     char *p_fld;
0253     char *p_dat;
0254     BFLDLEN step;
0255     int iocc=0;
0256     BFLDID *p_bfldid;
0257     int cmp_ret;
0258     ndrx_ubf_tls_bufval_t tmp_stor;
0259     UBF_LOG(log_debug, "%s: bfldid: %d", fn, bfldid);
0260 
0261     /* find first occurrence */
0262     p_fld=get_fld_loc(p_ub, bfldid, 0,
0263                             &dtype,
0264                             &last_checked,
0265                             NULL,
0266                             &last_occ,
0267                             NULL);
0268     
0269     /* loop over the data */
0270     while (NULL!=p_fld)
0271     {
0272         dtype_ext1 = &G_dtype_ext1_map[dtype->fld_type];
0273             
0274         step = dtype->p_next(dtype, p_fld, &dlen);
0275         
0276         /* get the occ data / support for views / custom prep */
0277         if (NULL!=dtype_ext1->p_prep_ubfp)
0278         {
0279             /* translate to value */
0280             p_dat=dtype_ext1->p_prep_ubfp(dtype_ext1, 
0281                     &tmp_stor, p_fld);
0282         }
0283         else
0284         {
0285            /* Move us to start of the data. */
0286             p_dat = p_fld+dtype_ext1->hdr_size;
0287         }
0288         
0289         /* Now do compare */
0290         cmp_ret=dtype_ext1->p_cmp(dtype_ext1, p_dat, dlen, buf, len, 0L);
0291         
0292         if (EXTRUE==cmp_ret)
0293         {
0294             UBF_LOG(log_debug, "%s: Found occurrence: %d", fn, iocc);
0295             ret=iocc;
0296             break; /* <<< BREAKE on Found. */
0297         }
0298         else if (EXFALSE==cmp_ret)
0299         {
0300             p_fld+=step;
0301             /* Align error */
0302             if (CHECK_ALIGN(p_fld, p_ub, hdr))
0303             {
0304                 ndrx_Bset_error_fmt(BALIGNERR, "%s: Pointing to non UBF area: %p",
0305                                             fn, p_fld);
0306                 break; /* <<<< BREAK!!! */
0307             }
0308             p_bfldid = (BFLDID *)p_fld;
0309 
0310             if (*p_bfldid!=bfldid)
0311             {
0312                 /* Next field is not ours! */
0313                 break; /* <<< BREAK!!! */
0314             }
0315             else
0316             {
0317                 iocc++;
0318             }
0319         } /* if/else */
0320         else if (EXFAIL==cmp_ret)
0321         {
0322             /* Regexp failed or malloc problems: error should be already set! */
0323             break; /* <<< BREAK!!! */
0324         }
0325     }/* while */
0326 
0327     if (!ndrx_Bis_error() && ret==EXFAIL )
0328     {
0329         /* The we do not have a result */
0330         ndrx_Bset_error_fmt(BNOTPRES, "%s: Occurrance of field %d not found last occ: %hd",
0331                                     fn, bfldid, iocc);
0332     }
0333     
0334     UBF_LOG(log_debug, "%s: return %d", fn, ret);
0335 
0336     return ret;
0337 }
0338 
0339 /**
0340  * Internal version of CBfindocc.
0341  * will re-use _Bfindocc for searching the occurrance but in extra will conver the
0342  * data type
0343  * @param p_ub - ptr to FB
0344  * @param bfldid - field ID to search for
0345  * @param value - value to search for
0346  * @param len - len for carray
0347  * @param usrtype - user data type specified
0348  * @return -1 (FAIL)/>=0 occurrance
0349  */
0350 expublic BFLDOCC ndrx_CBfindocc (UBFH *p_ub, BFLDID bfldid, char * value, BFLDLEN len, int usrtype)
0351 {
0352     int ret=EXFAIL;
0353     int cvn_len=0;
0354     char *cvn_buf;
0355     char tmp_buf[CF_TEMP_BUF_MAX];
0356     int to_type = (bfldid>>EFFECTIVE_BITS);
0357     /* Buffer management */
0358     char *alloc_buf = NULL;
0359     char *p;
0360     char *fn = "_CBfindocc";
0361     /* if types are the same then do direct call */
0362     if (usrtype==to_type)
0363     {
0364         UBF_LOG(log_debug, "%s: the same types - direct call!", fn);
0365         return ndrx_Bfindocc(p_ub, bfldid, value, len); /* <<<< RETURN!!! */
0366     }
0367 
0368     /* if types are not the same then go the long way... */
0369 
0370     /* Allocate the buffer dynamically or statically */
0371     if (NULL==(p=ndrx_ubf_get_cbuf(usrtype, to_type, tmp_buf,value, len, 
0372             &alloc_buf, &cvn_len, CB_MODE_DEFAULT, 0)))
0373     {
0374         UBF_LOG(log_error, "%s: Malloc failed!", fn);
0375         return EXFAIL; /* <<<< RETURN!!!! */
0376     }
0377 
0378     /* Convert the value */
0379     cvn_buf = ndrx_ubf_convert(usrtype, CNV_DIR_IN, value, len,
0380                         to_type, p, &cvn_len);
0381 
0382     if (NULL!=cvn_buf)
0383     {   /* In case of string, we do not want regexp processing, so do not pass the len */
0384         ret=ndrx_Bfindocc(p_ub, bfldid, cvn_buf, (BFLD_STRING!=to_type?cvn_len:0));
0385     }
0386     else
0387     {
0388         UBF_LOG(log_error, "%s: failed to convert data!", fn);
0389         /* Error should be provided by conversation function */
0390         ret=EXFAIL;
0391     }
0392 
0393     /* Free up buffer */
0394     if (NULL!=alloc_buf)
0395     {
0396         UBF_LOG(log_debug, "%s: free alloc_buf", fn);
0397         NDRX_FREE(alloc_buf);
0398     }
0399     
0400     UBF_LOG(log_debug, "%s: return %d", fn, ret);
0401 
0402     return ret;
0403 }
0404 
0405 /**
0406  * Backend impelmentation for Bfindlast
0407  * @param p_ub
0408  * @param bfldid
0409  * @param occ - returning occ number.
0410  * @param len
0411  * @return 
0412  */
0413 expublic char * ndrx_Bfindlast (UBFH * p_ub, BFLDID bfldid,
0414                                                 BFLDOCC *occ,
0415                                                 BFLDLEN * len)
0416 {
0417     
0418     int data_type = (bfldid>>EFFECTIVE_BITS);
0419     dtype_str_t *dtype;
0420     char *last_checked=NULL;
0421     char *last_match=NULL;
0422     int last_occ;
0423     char *ret = NULL;
0424     dtype_ext1_t *dtype_ext1;
0425     char fn[] = "_Bfindlast";
0426 
0427     UBF_LOG(log_debug, "%s: bfldid: %d occ: %hd", fn, bfldid, occ);
0428 
0429     get_fld_loc(p_ub, bfldid, -2,
0430                             &dtype,
0431                             &last_checked,
0432                             &last_match,
0433                             &last_occ,
0434                             NULL);
0435 
0436     dtype = &G_dtype_str_map[data_type];
0437     /* Get the data size of Bfind */
0438     if (EXFAIL!=last_occ && !ndrx_Bis_error())
0439     {
0440         int dlen;
0441 
0442         /* Return the occurrence found. */
0443         if (NULL!=occ)
0444             *occ = last_occ;
0445 
0446         ret = last_match;
0447         /* Get the payload size */
0448         if (NULL!=len)
0449         {
0450            dtype->p_next(dtype, (char *)ret, len);
0451         }
0452 
0453         dtype_ext1 = &G_dtype_ext1_map[data_type];
0454         dlen = dtype_ext1->hdr_size;
0455         
0456         if (NULL!=dtype_ext1->p_prep_ubfp)
0457         {
0458             /* Move to data via tls storage */
0459             ret=dtype_ext1->p_prep_ubfp(dtype_ext1, 
0460                     &G_ubf_tls->ndrx_Bfindlast_tls_stor, ret);
0461         }
0462         else
0463         {
0464             /* Move us to start of the data. */
0465             ret+=dlen;
0466         }
0467     }
0468     else
0469     {
0470         /* set the error that field is not found */
0471         ndrx_Bset_error(BNOTPRES);
0472     }
0473 
0474     UBF_LOG(log_debug, "%s: return: %p occ: %d", fn, ret, last_occ);
0475 /***************************************** DEBUG *******************************/
0476     #ifdef UBF_API_DEBUG
0477     if (NULL!=ret)
0478     {
0479         dtype_ext1->p_dump_data(dtype_ext1, "_Bfindlast got data", ret, len);
0480     }
0481     #endif
0482 /*******************************************************************************/
0483     
0484     return ret;
0485 }
0486 
0487 /* vim: set ts=4 sw=4 et smartindent: */