Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Implementation of Bcmp and Bsubset
0003  *   TODO: Might increase speed if we would use Bfind?
0004  *
0005  * @file bcmp.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 <string.h>
0038 #include <stdio.h>
0039 #include <stdlib.h>
0040 #include <memory.h>
0041 #include <errno.h>
0042 
0043 #include <ubf.h>
0044 #include <ubf_int.h>    /* Internal headers for UBF... */
0045 #include <fdatatype.h>
0046 #include <ferror.h>
0047 #include <fieldtable.h>
0048 #include <ndrstandard.h>
0049 #include <ndebug.h>
0050 #include <cf.h>
0051 
0052 #include "userlog.h"
0053 /*---------------------------Externs------------------------------------*/
0054 /*---------------------------Macros-------------------------------------*/
0055 /*---------------------------Enums--------------------------------------*/
0056 /*---------------------------Typedefs-----------------------------------*/
0057 /*---------------------------Globals------------------------------------*/
0058 /*---------------------------Statics------------------------------------*/
0059 /*---------------------------Prototypes---------------------------------*/
0060 
0061 /**
0062  * Compare two UBF buffers
0063  * @param p_ubf1 buffer 1 to compare
0064  * @param p_ubf2 buffer 2 to compare with 1
0065  * @return  0 - buffers are equal
0066  * -1 - first ubf1 field is less than ubf2, value of 1 is less than 2
0067  *      ubf1 have less fields than ubf2
0068  * 1 - vice versa
0069  * -2 - for error
0070  */
0071 expublic int ndrx_Bcmp(UBFH *p_ubf1, UBFH *p_ubf2)
0072 {
0073     int ret = EXSUCCEED;
0074     Bnext_state_t state1;
0075     Bnext_state_t state2;
0076     BFLDID bfldid1;
0077     BFLDOCC occ1;
0078 
0079     BFLDID bfldid2;
0080     BFLDOCC occ2;
0081 
0082     BFLDLEN len1;
0083     BFLDLEN len2;
0084     
0085     int ret1;
0086     int ret2;
0087     
0088     char *buf1;
0089     char *buf2;
0090     
0091     dtype_ext1_t *typ;
0092     int typcode;
0093     
0094     memset(&state1, 0, sizeof(state1));
0095     memset(&state2, 0, sizeof(state2));
0096     
0097     bfldid1 = BFIRSTFLDID;
0098     bfldid2 = BFIRSTFLDID;
0099     while (1)
0100     {
0101         ret1=ndrx_Bnext(&state1, p_ubf1, &bfldid1, &occ1, NULL, &len1, &buf1);
0102         ret2=ndrx_Bnext(&state2, p_ubf2, &bfldid2, &occ2, NULL, &len2, &buf2);
0103         
0104         if (EXFAIL==ret1)
0105         {
0106             /* error must be set */
0107             UBF_LOG(log_debug, "buffer1 Bnext failed");
0108             ret=-2;
0109             goto out;
0110         }
0111 
0112         if (EXFAIL==ret2)
0113         {
0114             /* error must be set */
0115             UBF_LOG(log_debug, "buffer2 Bnext failed");
0116             ret=-2;
0117             goto out;
0118         }
0119 
0120         if (EXTRUE!=ret1 && EXTRUE!=ret2)
0121         {
0122             UBF_LOG(log_debug, "EOF reached buffers %p vs %p equal",
0123                     p_ubf1, p_ubf2);
0124             
0125             ret = 0;
0126             goto out;
0127         }
0128         else if (EXTRUE!=ret1 && EXTRUE==ret2)
0129         {
0130             ret=-1;
0131             goto out;
0132         }
0133         else if (EXTRUE==ret1 && EXTRUE!=ret2)
0134         {
0135             ret=1;
0136             goto out;
0137         }
0138         /* compare IDs */
0139         else if (bfldid1 < bfldid2)
0140         {
0141             ret=-1;
0142             goto out;
0143         }
0144         else if (bfldid1 > bfldid2)
0145         {
0146             ret=1;
0147             goto out;
0148         }
0149         
0150         /* ok, ids are equal, lets compare by value */
0151         
0152         typcode = Bfldtype(bfldid1);
0153         
0154         if (typcode > BFLD_MAX || typcode < BFLD_MIN)
0155         {
0156             ret=-2;
0157             userlog("Invalid type id found in buffer %p: %d - corrupted UBF buffer?", 
0158                     p_ubf1, typcode);
0159             UBF_LOG(log_error, "Invalid type id found in buffer %p: %d "
0160                     "- corrupted UBF buffer?",  p_ubf1, typcode);
0161             /* set error */
0162             ndrx_Bset_error_fmt(BNOTFLD, "Invalid type id found in buffer %p: %d "
0163                     "- corrupted UBF buffer?", p_ubf1, typcode);
0164             
0165             goto out;
0166         }
0167 
0168         typ = &G_dtype_ext1_map[typcode];
0169 
0170         ret = typ->p_cmp(typ, buf1, len1, buf2, len2, UBF_CMP_MODE_STD);
0171         
0172         if (ret < 0)
0173         {
0174             /* so fields are different */
0175             ret = -1;
0176             goto out;
0177         }
0178         else if (ret > 0)
0179         {
0180             ret = 1;
0181             goto out;
0182         }
0183     }
0184     
0185 out:
0186 
0187     return ret;
0188 }
0189 
0190 /**
0191  * Compares the buffer and returns TRUE if all p_ubf2 fields and values 
0192  * are present in ubf1
0193  * @param p_ubf1 haystack
0194  * @param p_ubf2 needle
0195  * @param level recursion level for debug
0196  * @return EXFALSE not a subset, EXTRUE is subset, EXFAIL (error occurred)
0197  */
0198 expublic int ndrx_Bsubset(UBFH *p_ubf1, UBFH *p_ubf2, int level)
0199 {
0200     /* so basically we loop over the p_ubf2 and check every field obf ubf2
0201      * presence in ubf1 and compare their values... */
0202     
0203     int ret = EXSUCCEED;
0204     Bnext_state_t state2;
0205 
0206     BFLDID bfldid2;
0207     BFLDOCC occ2;
0208 
0209     BFLDLEN len1;
0210     BFLDLEN len2;
0211 
0212     char *buf1 = NULL;
0213     char *buf2 = NULL;
0214     
0215     int ret2;
0216     
0217     dtype_ext1_t *typ;
0218     int typcode;
0219     
0220     UBF_LOG(log_debug, "Matching %p vs %p at level %d", p_ubf1, p_ubf2, level);
0221     
0222     memset(&state2, 0, sizeof(state2));
0223     
0224     bfldid2 = BFIRSTFLDID;
0225     while (1)
0226     {
0227         ret2=ndrx_Bnext(&state2, p_ubf2, &bfldid2, &occ2, NULL, &len2, &buf2);    
0228         
0229         if (0==ret2)
0230         {
0231             /* ok we have EOF of buffer, equals */
0232             ret=EXTRUE;
0233             goto out;
0234         }
0235         else if (EXFAIL==ret2)
0236         {
0237             /* something is have failed, Bnext have set error  */
0238             EXFAIL_OUT(ret);
0239         }
0240         
0241         /* got the field, now read from haystack */
0242         
0243         buf1=ndrx_Bfind(p_ubf1, bfldid2, occ2, &len1, NULL);
0244         
0245         if (NULL==buf1)
0246         {
0247             if (BNOTPRES!=Berror)
0248             {
0249                 UBF_LOG(log_error, "Failed to get [%d] occ [%d] from haystack buffer", 
0250                         bfldid2, occ2);
0251                 EXFAIL_OUT(ret);
0252             }
0253             
0254             ndrx_Bunset_error();
0255             /* in this case needle is not part of haystack */
0256             ret = EXFALSE;
0257             goto out;
0258         }
0259         
0260         /* we have got the value, now compare boths  */
0261         
0262         typcode = Bfldtype(bfldid2);
0263         
0264         if (typcode > BFLD_MAX || typcode < BFLD_MIN)
0265         {
0266             ret=-1;
0267             userlog("Invalid type id found in buffer %p: %d - corrupted UBF buffer?", 
0268                     p_ubf1, typcode);
0269             UBF_LOG(log_error, "Invalid type id found in buffer %p: %d "
0270                     "- corrupted UBF buffer?",  p_ubf1, typcode);
0271             /* set error */
0272             ndrx_Bset_error_fmt(BNOTFLD, "Invalid type id found in buffer %p: %d "
0273                     "- corrupted UBF buffer?", p_ubf1, typcode);
0274             
0275             goto out;
0276         }
0277 
0278         /* If this is UBF buffer type, then we shall step in as in recursion */
0279         
0280         if (typcode==BFLD_UBF)
0281         {
0282             UBF_LOG(log_debug, "Stepping into UBF for UBF fldid %d", bfldid2);
0283             ret=ndrx_Bsubset((UBFH *)buf1, (UBFH *)buf2, level+1);
0284         }
0285         else
0286         {
0287             typ = &G_dtype_ext1_map[typcode];
0288             ret=typ->p_cmp(typ, buf1, len1, buf2, len2, 0);
0289         }
0290         
0291         if (EXFALSE==ret)
0292         {
0293             UBF_LOG(log_debug, "fields are different, not a subset");
0294             ret=EXFALSE;
0295             goto out;
0296         }
0297         else if (EXFAIL==ret)
0298         {
0299             UBF_LOG(log_error, "error comparing fields");
0300             ret=-1;
0301             goto out;
0302         }
0303     }
0304     
0305 out:
0306     return ret;
0307 }
0308 
0309 /* vim: set ts=4 sw=4 et smartindent: */