Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Real time handling routines
0003  *  note we use here standard malloc, as that is the same as which is used by
0004  *  flex/bison.
0005  * @file ddr_atmi.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 #ifndef _GNU_SOURCE
0036 #define _GNU_SOURCE
0037 #endif
0038 
0039 #include <string.h>
0040 #include <stdio.h>
0041 #include <stdlib.h>
0042 #include <memory.h>
0043 #include <errno.h>
0044 #include <regex.h>
0045 
0046 #include <ndrx_intdef.h>
0047 #include <exregex.h>
0048 #include <ndrx_ddr.h>
0049 #include <ndrxd.h>
0050 #include <typed_buf.h>
0051 #include "expr_range.tab.h"
0052 #include "utlist.h"
0053 #include "lcfint.h"
0054 #include <atmi_shm.h>
0055 #include <lcfint.h>
0056 /*---------------------------Externs------------------------------------*/
0057 /*---------------------------Macros-------------------------------------*/
0058 /*---------------------------Enums--------------------------------------*/
0059 /*---------------------------Typedefs-----------------------------------*/
0060 /*---------------------------Globals------------------------------------*/
0061 
0062 expublic ndrx_ddr_parser_t ndrx_G_ddrp;      /**< Parsing time attributes*/
0063 /*---------------------------Statics------------------------------------*/
0064 exprivate regex_t M_floatexp;       /**< float check regexp             */
0065 exprivate regex_t M_intexp;         /**< Integer expression             */
0066 exprivate int M_floatexp_comp=EXFALSE;  /**< is float regexp compiled?  */
0067 exprivate int M_was_loaded=EXFALSE;       /**< Was routing loaded?      */
0068 exprivate int M_do_reload=EXFALSE;        /**< Is reload waiting        */
0069 exprivate int M_do_reload_cycles=EXFAIL;  /**< Number of sanity cycles, till apply */
0070 
0071 /*---------------------------Prototypes---------------------------------*/
0072 
0073 /**
0074  * Perform sanity checks of scheduled load
0075  */
0076 expublic void ndrx_ddr_apply_sanity(void)
0077 {
0078     if (M_do_reload)
0079     {
0080         M_do_reload_cycles++;
0081         
0082         if (M_do_reload_cycles > G_app_config->ddrreload)
0083         {
0084             ndrx_ddr_install();
0085         }
0086     }
0087 }
0088 
0089 /**
0090  * Install the DDR data to shared memory segments, swap the counters.
0091  * This also must detect, if there are no services, then DDR shall be disabled.
0092  * if installing then segments must be swapped
0093  */
0094 expublic void ndrx_ddr_install(void)
0095 {
0096     int do_disable = EXFALSE;
0097     int page;
0098     
0099     NDRX_LOG(log_info, "Installing DDR infos to shared memory");
0100     /* only one time please*/
0101     M_do_reload=EXFALSE;
0102     M_was_loaded=EXTRUE;
0103     
0104     if (NULL==G_app_config->services)
0105     {
0106         do_disable=EXTRUE;
0107     }
0108     
0109     if (do_disable)
0110     {
0111         ndrx_G_shmcfg->use_ddr=EXFALSE;
0112     }
0113     else if (!ndrx_G_shmcfg->use_ddr)
0114     {
0115         NDRX_LOG(log_info, "Loading NEW DDR, page 0");
0116         /* copy off just new config, start with page 0*/
0117         ndrx_G_shmcfg->ddr_page = 0;
0118         ndrx_G_shmcfg->ddr_ver1++;
0119         memcpy(ndrx_G_routcrit.mem, G_app_config->routing_block, G_atmi_env.rtcrtmax);
0120         memcpy(ndrx_G_routsvc.mem, G_app_config->services_block, G_atmi_env.rtsvcmax * sizeof(ndrx_services_t));
0121         
0122         /* Now service start to route ... */
0123         ndrx_G_shmcfg->use_ddr = 1;
0124         
0125     }
0126     else
0127     {
0128         /* check the current page, if cirt / or rout is not the same
0129          * then to new page copy all the routing blobs
0130          */
0131         page = ndrx_G_shmcfg->ddr_page;
0132         
0133         /* check current page is it changed or not ?  */
0134         
0135         if (0 == memcmp(ndrx_G_routcrit.mem + page*G_atmi_env.rtcrtmax, 
0136                 G_app_config->routing_block, G_atmi_env.rtcrtmax) &&
0137                 
0138             0 == memcmp(ndrx_G_routsvc.mem + page*G_atmi_env.rtsvcmax * sizeof(ndrx_services_t), 
0139                 G_app_config->services_block, G_atmi_env.rtsvcmax * sizeof(ndrx_services_t))
0140                 )
0141         {
0142             NDRX_LOG(log_info, "DDR routing configuration not changed");
0143         }
0144         else
0145         {
0146             /* choose the new page */
0147             page+=1;
0148             
0149             if (page>=NDRX_LCF_DDR_PAGES)
0150             {
0151                 page=0;
0152             }
0153             
0154             NDRX_LOG(log_info, "DDR Changing configuration into page %d", page);
0155             
0156             ndrx_G_shmcfg->ddr_ver1++;
0157             memcpy(ndrx_G_routcrit.mem + page*G_atmi_env.rtcrtmax, 
0158                 G_app_config->routing_block, G_atmi_env.rtcrtmax);
0159             
0160             memcpy(ndrx_G_routsvc.mem + page*G_atmi_env.rtsvcmax * sizeof(ndrx_services_t), 
0161                 G_app_config->services_block, G_atmi_env.rtsvcmax * sizeof(ndrx_services_t));
0162             
0163             /* open new segment to processes to route. */
0164             ndrx_G_shmcfg->ddr_page = page;
0165         }
0166     }
0167 }
0168 
0169 /**
0170  * Load config
0171  * This will either schedule or apply directly if first start.
0172  */
0173 expublic void ndrx_ddr_apply(void)
0174 {
0175     /* Check the status, are we going to disable routing? if
0176      * so then we can to it directly too...
0177      */
0178     int do_disable = EXFALSE;
0179     
0180     if (NULL==G_app_config->services)
0181     {
0182         do_disable=EXTRUE;
0183     }
0184     
0185     if (!M_was_loaded || do_disable)
0186     {
0187         ndrx_ddr_install();
0188     }
0189     else
0190     {
0191         NDRX_LOG(log_info, "DDR routing change scheduled");
0192         M_do_reload=EXTRUE;
0193         M_do_reload_cycles=0;
0194     }
0195 }
0196 
0197 /**
0198  * Free up resources used by parser
0199  * @param ptr
0200  */
0201 expublic void ndrx_ddr_delete_buffer(void *ptr)
0202 {
0203     NDRX_FREE(ptr);
0204 }
0205 
0206 /**
0207  * Add sequence to the hashmap
0208  * What we need to do additionally is:
0209  * - check the integer types
0210  * - check the float types
0211  * - check that group contains valid symbols
0212  * If all OK, add the entry to linked list
0213  * @param seq parsed sequence
0214  * @param grp parsed group
0215  * @param is_mallocd is grp allocated by previous stages
0216  */
0217 expublic int ndrx_ddr_add_group(ndrx_routcritseq_dl_t * seq, char *grp, int is_mallocd)
0218 {
0219     int ret = EXSUCCEED;
0220     int len;
0221     char *dflt_group = "*";
0222     regex_t *p_rex = NULL;
0223     if (NULL==grp)
0224     {
0225         grp = dflt_group;
0226     }
0227     
0228     NDRX_LOG(log_debug, "Adding routing group: [%s]", grp);
0229     
0230     /* Number check:  */
0231     
0232     /* we run single threaded here, so no worry... */
0233     if (!M_floatexp_comp)
0234     {
0235         if (EXSUCCEED!=ndrx_regcomp(&M_floatexp, "^[-+]?(([0-9]*[.]?[0-9]+([ed][-+]?[0-9]+)?))$"))
0236         {
0237             NDRX_LOG(log_error, "Failed to compile regexp of tag float check");
0238             NDRXD_set_error_fmt(NDRXD_EOS, "(%s) Failed to compile regexp of tag float check near line %d!", 
0239                 G_sys_config.config_file_short, G_sys_config.last_line);
0240             EXFAIL_OUT(ret);
0241         }
0242         
0243         /* compile for longs too, then select which expression to use */
0244         
0245         if (EXSUCCEED!=ndrx_regcomp(&M_intexp, "^[+-]?([0-9])+$"))
0246         {
0247             NDRX_LOG(log_error, "Failed to compile regexp of tag int check");
0248             NDRXD_set_error_fmt(NDRXD_EOS, "(%s) Failed to compile regexp of tag int check near line %d!", 
0249                 G_sys_config.config_file_short, G_sys_config.last_line);
0250             EXFAIL_OUT(ret);
0251         }
0252         
0253         M_floatexp_comp=EXTRUE;
0254     }
0255     
0256     /* Check the group code -> cannot contain the @ */
0257     if (NULL!=strchr(grp, '@') || NULL!=strchr(grp, '/') || NULL!=strchr(grp, ' ') || NULL!=strchr(grp, '\t')
0258             || NULL!=strchr(grp, ','))
0259     {
0260         NDRX_LOG(log_error, "Invalid group code [%s]", grp);
0261         NDRXD_set_error_fmt(NDRXD_ESYNTAX, "(%s) Invalid group code [%s] near line %d", 
0262             G_sys_config.config_file_short, grp, G_sys_config.last_line);
0263         EXFAIL_OUT(ret);
0264     }
0265     
0266     len = strlen(grp);
0267     if (len > NDRX_DDR_GRP_MAX)
0268     {
0269         NDRX_LOG(log_error, "Group code [%s] too long max %d", grp, NDRX_DDR_GRP_MAX);
0270         NDRXD_set_error_fmt(NDRXD_ESYNTAX, "(%s) Group code [%s] too long max %d near line %d",
0271             G_sys_config.config_file_short, grp, NDRX_DDR_GRP_MAX, G_sys_config.last_line);
0272         EXFAIL_OUT(ret);
0273     }
0274     
0275     if (0==strcmp(grp, "*"))
0276     {
0277         seq->cseq.flags|= NDRX_DDR_FLAG_DEFAULT_GRP;
0278     }
0279     
0280     /* ok setup group code */
0281     NDRX_STRCPY_SAFE(seq->cseq.grp, grp);
0282     
0283     /* 
0284      * Resolve ranges
0285      */
0286     if (BFLD_DOUBLE==ndrx_G_ddrp.p_crit->routcrit.fieldtypeid ||
0287             BFLD_LONG==ndrx_G_ddrp.p_crit->routcrit.fieldtypeid
0288             )
0289     {
0290         
0291         if (BFLD_DOUBLE==ndrx_G_ddrp.p_crit->routcrit.fieldtypeid)
0292         {
0293             p_rex=&M_floatexp;
0294         }
0295         else
0296         {
0297             p_rex=&M_intexp;
0298         }
0299         
0300         /* calculate the final len: 
0301          */
0302         seq->cseq.len = sizeof(seq->cseq);
0303         
0304         /* check min / max if have min/max/default indications .. */
0305         if (seq->cseq.flags & NDRX_DDR_FLAG_DEFAULT_VAL ||
0306                 (seq->cseq.flags & NDRX_DDR_FLAG_MIN && seq->cseq.flags & NDRX_DDR_FLAG_MAX)
0307                 )
0308         {
0309             /* nothing todo */
0310         }
0311         else if (seq->cseq.flags & NDRX_DDR_FLAG_MIN)
0312         {
0313             /* we can setup max + validate string */
0314             
0315             if (EXSUCCEED!=ndrx_regexec(p_rex, seq->cseq.strrange))
0316             {
0317                 NDRX_LOG(log_error, "Invalid upper range [%s] for grp [%s] "
0318                         "routing [%s] buffer type [%s]", 
0319                         seq->cseq.strrange, grp,
0320                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype);
0321                 NDRXD_set_error_fmt(NDRXD_ESYNTAX, "(%s) Invalid upper range [%s] "
0322                         "for grp [%s] routing [%s] buffer type [%s] near line %d",
0323                         G_sys_config.config_file_short, seq->cseq.strrange, grp,
0324                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype,
0325                         G_sys_config.last_line);
0326                 EXFAIL_OUT(ret);
0327             }
0328             
0329             seq->cseq.upperd = ndrx_atof(seq->cseq.strrange);
0330             seq->cseq.upperl = atol(seq->cseq.strrange);
0331         }
0332         else if (seq->cseq.flags & NDRX_DDR_FLAG_MAX)
0333         {
0334             if (EXSUCCEED!=ndrx_regexec(p_rex, seq->cseq.strrange))
0335             {
0336                 NDRX_LOG(log_error, "Invalid lower range [%s] for grp [%s] "
0337                         "routing [%s] buffer type [%s]", 
0338                         seq->cseq.strrange, grp,
0339                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype);
0340                 NDRXD_set_error_fmt(NDRXD_ESYNTAX, "(%s) Invalid lower range [%s] "
0341                         "for grp [%s] routing [%s] buffer type [%s] near line %d",
0342                         G_sys_config.config_file_short,  seq->cseq.strrange, grp,
0343                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype,
0344                         G_sys_config.last_line);
0345                 EXFAIL_OUT(ret);
0346             }
0347             
0348             seq->cseq.lowerd = ndrx_atof(seq->cseq.strrange);
0349             seq->cseq.lowerl = atol(seq->cseq.strrange);
0350         }
0351         else
0352         {
0353             
0354             if (EXSUCCEED!=ndrx_regexec(p_rex, seq->cseq.strrange))
0355             {
0356                 NDRX_LOG(log_error, "Invalid lower range [%s] for grp [%s] "
0357                         "routing [%s] buffer type [%s]", 
0358                         seq->cseq.strrange, grp,
0359                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype);
0360                 NDRXD_set_error_fmt(NDRXD_ESYNTAX, "(%s) Invalid lower range [%s] "
0361                         "for grp [%s] routing [%s] buffer type [%s] near line %d",
0362                         G_sys_config.config_file_short,  seq->cseq.strrange, grp,
0363                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype,
0364                         G_sys_config.last_line);
0365                 EXFAIL_OUT(ret);
0366             }
0367             
0368             if (EXSUCCEED!=ndrx_regexec(p_rex, seq->cseq.strrange+seq->cseq.strrange_upper))
0369             {
0370                 NDRX_LOG(log_error, "Invalid upper range [%s] for grp [%s] "
0371                         "routing [%s] buffer type [%s]", 
0372                         seq->cseq.strrange, grp, 
0373                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype);
0374                 NDRXD_set_error_fmt(NDRXD_ESYNTAX, "(%s) Invalid upper range [%s] "
0375                         "for grp [%s] routing [%s] buffer type [%s] near line %d",
0376                         G_sys_config.config_file_short,  seq->cseq.strrange, grp,
0377                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype,
0378                         G_sys_config.last_line);
0379                 EXFAIL_OUT(ret);
0380             }
0381             
0382             seq->cseq.lowerd = ndrx_atof(seq->cseq.strrange);
0383             seq->cseq.lowerl = atol(seq->cseq.strrange);
0384             
0385             seq->cseq.upperd = ndrx_atof(seq->cseq.strrange+seq->cseq.strrange_upper);
0386             seq->cseq.upperl = atol(seq->cseq.strrange+seq->cseq.strrange_upper);
0387             
0388             if (seq->cseq.lowerd > seq->cseq.upperd)
0389             {
0390                 NDRX_LOG(log_error, "Lower [%lf] greater than upper [%lf] for grp [%s] "
0391                         "routing [%s] buffer type [%s]", 
0392                         seq->cseq.lowerd, seq->cseq.upperd, grp, 
0393                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype);
0394                 NDRXD_set_error_fmt(NDRXD_ESYNTAX, "(%s) Lower [%lf] greater than upper [%lf] for grp [%s] "
0395                         "routing [%s] buffer type [%s] near line %d",
0396                         G_sys_config.config_file_short,  seq->cseq.lowerd, 
0397                         seq->cseq.upperd, grp,
0398                         ndrx_G_ddrp.p_crit->routcrit.criterion, 
0399                         ndrx_G_ddrp.p_crit->routcrit.buftype,
0400                         G_sys_config.last_line);
0401                 EXFAIL_OUT(ret);
0402             }
0403         }
0404     }
0405     else
0406     {
0407         /* it is string OK -> leave as is ... 
0408          * Also here to calculate the size needs to understand
0409          * min/max/default  settings
0410          */
0411         if (seq->cseq.flags & NDRX_DDR_FLAG_DEFAULT_VAL ||
0412                 (seq->cseq.flags & NDRX_DDR_FLAG_MIN && seq->cseq.flags & NDRX_DDR_FLAG_MAX)
0413                 )
0414         {
0415             seq->cseq.len = sizeof(seq->cseq);
0416         }
0417         else if (seq->cseq.flags & NDRX_DDR_FLAG_MIN)
0418         {
0419             seq->cseq.len = sizeof(seq->cseq) + strlen(seq->cseq.strrange)+1;
0420         }
0421         else if (seq->cseq.flags & NDRX_DDR_FLAG_MAX)
0422         {
0423            seq->cseq.len = sizeof(seq->cseq) + strlen(seq->cseq.strrange)+1;
0424         }
0425         else
0426         {
0427             /* OK check there that strings follow the rules higher lower */
0428             if (strcmp(seq->cseq.strrange, seq->cseq.strrange + seq->cseq.strrange_upper) > 0)
0429             {
0430                 NDRX_LOG(log_error, "Lower [%s] greater than upper [%s] for grp [%s] "
0431                         "routing [%s] buffer type [%s]", 
0432                         seq->cseq.strrange, seq->cseq.strrange + seq->cseq.strrange_upper, grp, 
0433                         ndrx_G_ddrp.p_crit->routcrit.criterion, ndrx_G_ddrp.p_crit->routcrit.buftype);
0434                 NDRXD_set_error_fmt(NDRXD_ESYNTAX, "(%s) Lower [%s] greater than upper [%s] for grp [%s] "
0435                         "routing [%s] buffer type [%s] near line %d",
0436                         G_sys_config.config_file_short,  
0437                         seq->cseq.strrange, seq->cseq.strrange + seq->cseq.strrange_upper, grp,
0438                         ndrx_G_ddrp.p_crit->routcrit.criterion, 
0439                         ndrx_G_ddrp.p_crit->routcrit.buftype,
0440                         G_sys_config.last_line);
0441                 EXFAIL_OUT(ret);
0442             }
0443             
0444             /* both strings are used... */
0445             seq->cseq.len = sizeof(seq->cseq) + strlen(seq->cseq.strrange)+1
0446                     +strlen(seq->cseq.strrange + seq->cseq.strrange_upper)+1;
0447         }
0448     }
0449     
0450     
0451     /* have some debug... */
0452     NDRX_LOG(log_debug, "--- Adding Route [%s] group range ---", seq->cseq.grp);
0453     
0454     NDRX_LOG(log_debug, "CRITERION: %s", ndrx_G_ddrp.p_crit->routcrit.criterion);
0455     NDRX_LOG(log_debug, "BUFTYPE: %s", ndrx_G_ddrp.p_crit->routcrit.buftype);
0456     
0457     NDRX_LOG(log_debug, "lowerl: %ld", seq->cseq.lowerl);
0458     NDRX_LOG(log_debug, "upperl: %ld", seq->cseq.upperl);
0459     
0460     NDRX_LOG(log_debug, "lowerd: %lf", seq->cseq.lowerd);
0461     NDRX_LOG(log_debug, "upperd: %lf", seq->cseq.upperd);
0462     NDRX_LOG(log_debug, "len: %d (struct size: %d)", seq->cseq.len, sizeof(seq->cseq));
0463     NDRX_LOG(log_debug, "flags: %d", seq->cseq.flags);
0464     
0465     
0466     NDRX_LOG(log_debug, "MIN: %d", seq->cseq.flags & NDRX_DDR_FLAG_MIN);
0467     NDRX_LOG(log_debug, "MAX: %d", seq->cseq.flags & NDRX_DDR_FLAG_MAX);
0468     NDRX_LOG(log_debug, "DEFAULT VAL: %d", seq->cseq.flags & NDRX_DDR_FLAG_DEFAULT_VAL);
0469     NDRX_LOG(log_debug, "DEFAULT GRP: %d", seq->cseq.flags & NDRX_DDR_FLAG_DEFAULT_GRP);
0470     
0471     NDRX_LOG(log_debug, "strrange_upper: %d", seq->cseq.strrange_upper);
0472     NDRX_LOG(log_debug, "strrange: [%s]", seq->cseq.strrange);
0473     NDRX_LOG(log_debug, "strrange_upper: [%s]", seq->cseq.strrange+seq->cseq.strrange_upper);
0474     
0475     NDRX_LOG(log_debug, "-------------------------------------");
0476     
0477     /* add to DL finally */
0478     DL_APPEND(ndrx_G_ddrp.p_crit->seq, seq)
0479     ndrx_G_ddrp.p_crit->routcrit.rangesnr++;
0480 
0481 out:
0482     if (is_mallocd)
0483     {
0484         NDRX_FREE(grp);
0485     }
0486 
0487     if (EXSUCCEED!=ret)
0488     {
0489         /* not added to DL, thus will leak with out doing this... */
0490         NDRX_FREE(seq);
0491     }
0492     NDRX_LOG(log_error, "ret %d", ret);
0493     return ret;
0494 }
0495 
0496 /**
0497  * This will create routing criterion sequence entry
0498  * @param range_min
0499  * @param range_max
0500  * @return linked list sequence object
0501  */
0502 expublic ndrx_routcritseq_dl_t * ndrx_ddr_new_rangeexpr(char *range_min, char *range_max)
0503 {
0504     int str_min_sz=0;
0505     int str_max_sz=0;
0506     ndrx_routcritseq_dl_t *ret=NULL;
0507     int flags=0;
0508     int sz;
0509     
0510     if (NULL==range_min && NULL==range_max)
0511     {
0512         flags|=NDRX_DDR_FLAG_DEFAULT_VAL;
0513         NDRX_LOG(log_debug, "DEFAULT range");
0514     }
0515     else if (NULL==range_min)
0516     {
0517         flags|=NDRX_DDR_FLAG_MIN;
0518         str_max_sz=strlen(range_max)+1;
0519         
0520         NDRX_LOG(log_debug, "range_max=[%s]", range_max);
0521     }
0522     else if (NULL==range_max)
0523     {
0524         flags|=NDRX_DDR_FLAG_MAX;
0525         str_min_sz=strlen(range_min)+1;
0526         NDRX_LOG(log_debug, "range_min=[%s]", range_min);
0527     }
0528     else
0529     {
0530         /* both strings are used */
0531         str_min_sz=strlen(range_min)+1;
0532         str_max_sz=strlen(range_max)+1;
0533         
0534         NDRX_LOG(log_debug, "range_min=[%s]", range_min);
0535         NDRX_LOG(log_debug, "range_max=[%s]", range_max);
0536     }
0537     
0538     sz = sizeof(ndrx_routcritseq_dl_t) + str_max_sz + str_min_sz;
0539     ret = NDRX_MALLOC(sz);
0540     
0541     if (NULL==ret)
0542     {
0543         NDRX_LOG(log_error, "(%s) malloc %d bytes!", 
0544                 G_sys_config.config_file_short, sz);
0545         NDRXD_set_error_fmt(NDRXD_EOS, "(%s) malloc %d bytes! near line %d", 
0546                 G_sys_config.config_file_short, sz, G_sys_config.last_line);
0547         goto out;
0548     }
0549     
0550     memset(ret, 0, sz);
0551     
0552     ret->cseq.flags=flags;
0553     ret->cseq.strrange_upper=0;
0554 
0555     if ( !((flags & NDRX_DDR_FLAG_MIN) ||
0556             (flags & NDRX_DDR_FLAG_MAX) || (flags & NDRX_DDR_FLAG_DEFAULT_VAL)
0557             ))
0558     {
0559         
0560         /* both values are used */
0561         NDRX_STRCPY_SAFE_DST(ret->cseq.strrange, range_min, sz);
0562         
0563         /* this is where upper starts */
0564         ret->cseq.strrange_upper=str_min_sz;
0565         NDRX_STRCPY_SAFE_DST((ret->cseq.strrange+str_min_sz), range_max, str_max_sz);
0566     }
0567     else if (flags & NDRX_DDR_FLAG_MAX)
0568     {
0569         /* only min is stored */
0570         NDRX_STRCPY_SAFE_DST(ret->cseq.strrange, range_min, sz);
0571     }
0572     else if (flags & NDRX_DDR_FLAG_MIN)
0573     {
0574         NDRX_STRCPY_SAFE_DST(ret->cseq.strrange, range_max, sz);
0575     }
0576     
0577 out:
0578     
0579     
0580     if (NULL!=range_min)
0581     {
0582         NDRX_FREE(range_min);
0583     }
0584 
0585     /* free if having different pointers */
0586     if (NULL!=range_max && range_max!=range_min)
0587     {
0588         NDRX_FREE(range_max);
0589     }
0590 
0591     return ret;
0592     
0593 }
0594 /**
0595  * Allocate range value with sign, if having the one
0596  * @param range range token
0597  * @param is_negative is negative?
0598  * @param dealloc - remove the range
0599  * @return NULL in case of error
0600  */
0601 expublic char *ndrx_ddr_new_rangeval(char *range, int is_negative, int dealloc)
0602 {
0603     char *ret;
0604     int len;
0605     
0606     if (!is_negative)
0607     {
0608         ret=NDRX_STRDUP(range);
0609     }
0610     else
0611     {
0612         NDRX_ASPRINTF(&ret, &len, "-%s", range);
0613     }
0614     
0615     if (dealloc)
0616     {
0617         NDRX_FREE(range);
0618     }
0619     
0620     return ret;
0621 }
0622 
0623 /**
0624  * Generate parsing error
0625  * @param s
0626  * @param ...
0627  */
0628 void ddrerror(char *s, ...)
0629 {
0630     /* Log only first error! */
0631     if (EXFAIL!=ndrx_G_ddrp.error)
0632     {
0633         va_list ap;
0634         char errbuf[2048];
0635         int len;
0636 
0637         va_start(ap, s);
0638         snprintf(errbuf, sizeof(errbuf), "(%s) Routing range of [%s] buftype [%s]. "
0639                 "Near line %d, near expr of %d-%d: ", 
0640                 G_sys_config.config_file_short,
0641                 ndrx_G_ddrp.p_crit->routcrit.criterion, 
0642                 ndrx_G_ddrp.p_crit->routcrit.buftype,
0643                 G_sys_config.last_line,
0644                 ddrlloc.first_column, ddrlloc.last_column);
0645         len=strlen(errbuf);
0646         vsnprintf(errbuf+len, sizeof(errbuf)-len, s, ap);
0647         va_end(ap);
0648 
0649         if (NDRXD_is_error())
0650         {
0651           /* append message */
0652           NDRXD_append_error_msg(errbuf);
0653         }
0654         else
0655         {
0656           NDRXD_set_error_msg(NDRXD_ESYNTAX, errbuf);
0657         }
0658 
0659         ndrx_G_ddrp.error = EXFAIL;
0660     }
0661 }
0662 
0663 extern void ddr_scan_string (char *yy_str  );
0664 extern int ddrlex_destroy  (void);
0665 extern int ndrx_G_ddrcolumn;
0666 /**
0667  * Parse range
0668  * @param p_crit current criterion in parse subject
0669  * @return EXSUCCEED/EXFAIL
0670  */
0671 exprivate int ndrx_parse_range(ndrx_routcrit_typehash_t *p_crit)
0672 {
0673     int ret = EXSUCCEED;
0674     memset(&ndrx_G_ddrp, 0, sizeof(ndrx_G_ddrp));
0675     ndrx_G_ddrp.p_crit=p_crit;
0676     /* init the string builder */
0677     ndrx_growlist_init(&ndrx_G_ddrp.stringbuffer, 200, sizeof(char));
0678     
0679     /* start to parse... */
0680     
0681     ndrx_G_ddrcolumn=0;
0682     NDRX_LOG(log_info, "Parsing range: [%s]", p_crit->ranges);
0683     ddr_scan_string(p_crit->ranges);
0684             
0685     if (EXSUCCEED!=ddrparse() || EXSUCCEED!=ndrx_G_ddrp.error)
0686     {
0687         NDRX_LOG(log_error, "Failed to parse range: [%s]", p_crit->ranges);
0688         NDRXD_set_error_fmt(NDRXD_EOS, "(%s) failed to parse range near line %d", 
0689                 G_sys_config.config_file_short, p_crit->ranges, G_sys_config.last_line);
0690         
0691         /* free parsers... */
0692         ddrlex_destroy();
0693         
0694         
0695         /* well if we hav */
0696         
0697         EXFAIL_OUT(ret);
0698     }
0699     ddrlex_destroy();
0700     
0701 out:
0702     /* free up string buffer */
0703     ndrx_growlist_free(&ndrx_G_ddrp.stringbuffer);
0704 
0705     return ret;    
0706 }
0707 
0708 /**
0709  * Lookup the criterion in hashmap, if not found, just add
0710  * @param config current config loading
0711  * @param criterion criterion code to lookup
0712  * @return NULL in case of failure
0713  */
0714 exprivate ndrx_routcrit_hash_t * ndrx_criterion_get(config_t *config, char *criterion)
0715 {
0716     ndrx_routcrit_hash_t *ret=NULL;
0717     int err;
0718     int len = strlen(criterion);
0719     
0720     if (len > NDRX_DDR_CRITMAX)
0721     {
0722         NDRX_LOG(log_error, "(%s) Invalid criterion name [%s] len is %d, but max is %d"
0723                 " near line %d",
0724                 G_sys_config.config_file_short, criterion, len, NDRX_DDR_CRITMAX,
0725                 G_sys_config.last_line);
0726         NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Invalid criterion name [%s] len is %d but max is %d"
0727                 " near line %d",
0728                 G_sys_config.config_file_short, criterion, len, NDRX_DDR_CRITMAX,
0729                 G_sys_config.last_line);
0730         goto out;
0731     }
0732     
0733     if (0==len)
0734     {
0735         NDRX_LOG(log_error, "(%s) Empty criterion name",
0736                 G_sys_config.config_file_short);
0737         NDRXD_set_error_fmt(NDRXD_ECFGINVLD, "(%s) Empty criterion name near line %d",
0738                 G_sys_config.config_file_short,
0739                 G_sys_config.last_line);
0740         goto out;
0741     }
0742     
0743     EXHASH_FIND_STR(config->cirthash, criterion, ret);
0744     
0745     if (NULL==ret)
0746     {
0747         /* Alloc the criterion */
0748         ret = NDRX_MALLOC(sizeof(ndrx_routcrit_hash_t));
0749         
0750         if (NULL==ret)
0751         {
0752             err = errno;
0753             
0754             NDRX_LOG(log_error, "(%s) Failed to malloc %d byte (ndrx_routcrit_hash_t): %s", 
0755                     G_sys_config.config_file_short, sizeof(ndrx_routcrit_hash_t), strerror(err));
0756             
0757             NDRXD_set_error_fmt(NDRXD_EOS, "(%s) Failed to malloc %d byte (ndrx_routcrit_hash_t): %s"
0758                     " near line %d", 
0759                     G_sys_config.config_file_short, sizeof(ndrx_routcrit_hash_t), strerror(err),
0760                     G_sys_config.last_line);
0761             goto out;
0762         }
0763         
0764         memset(ret, 0, sizeof(ndrx_routcrit_hash_t));
0765         
0766         NDRX_STRCPY_SAFE(ret->criterion, criterion);
0767         EXHASH_ADD_STR(config->cirthash, criterion, ret);
0768     }
0769     
0770 out:
0771     return ret;
0772 }
0773 
0774 /**
0775  * Parse one route entry
0776  * @param config current config loading
0777  * @param doc
0778  * @param cur
0779  * @param is_defaults is this parsing of default
0780  * @param p_defaults default settings
0781  * @return EXSUCCEED/EXFAIL
0782  */
0783 expublic int ndrx_service_parse(config_t *config, xmlDocPtr doc, xmlNodePtr cur,
0784         int is_defaults, ndrx_services_hash_t *p_defaults)
0785 {
0786     int ret=EXSUCCEED;
0787     xmlAttrPtr attr;
0788     ndrx_services_hash_t *p_svc=NULL, *elt=NULL;
0789     char *p;
0790     
0791     /* service shall not be defined */
0792     
0793     if (is_defaults)
0794     {
0795         p_svc=p_defaults;
0796     }
0797     else
0798     {
0799         /* first of all, we need to get server name from attribs */
0800         p_svc = NDRX_MALLOC(sizeof(ndrx_services_hash_t));
0801         if (NULL==p_svc)
0802         {
0803             NDRX_LOG(log_error, "malloc failed for ndrx_routsvc_t!");
0804             NDRXD_set_error_fmt(NDRXD_EOS, "(%s) malloc failed for srvnode! near line %d", 
0805                     G_sys_config.config_file_short, G_sys_config.last_line);
0806             EXFAIL_OUT(ret);
0807         }
0808         memcpy(p_svc, p_defaults, sizeof(ndrx_services_hash_t));
0809     }
0810     
0811     for (attr=cur->properties; attr; attr = attr->next)
0812     {
0813         p = (char *)xmlNodeGetContent(attr->children);
0814         
0815         if (0==strcmp((char *)attr->name, "svcnm"))
0816         {
0817             /* check the name max */
0818             if (strlen(p) > XATMI_SERVICE_NAME_LENGTH)
0819             {
0820                 NDRX_LOG(log_error, "(%s) Too long service name [%s] in <services> section max %d", 
0821                     G_sys_config.config_file_short, p, XATMI_SERVICE_NAME_LENGTH);
0822                 NDRXD_set_error_fmt(NDRXD_ECFGINVLD, "(%s) Too long service name "
0823                         "[%s] in <services> section max %d near line %d", 
0824                     G_sys_config.config_file_short, p, XATMI_SERVICE_NAME_LENGTH,
0825                     G_sys_config.last_line);
0826                 xmlFree(p);
0827                 EXFAIL_OUT(ret);
0828             }
0829             NDRX_STRCPY_SAFE(p_svc->svcnm, p);
0830             NDRX_STRCPY_SAFE(p_svc->routsvc.svcnm, p);
0831             
0832         }
0833         else if (0==strcmp((char *)attr->name, "prio"))
0834         {
0835             p_svc->routsvc.prio = atoi(p);
0836 
0837             if (p_svc->routsvc.prio<NDRX_MSGPRIO_MIN ||
0838                 p_svc->routsvc.prio>NDRX_MSGPRIO_MAX)
0839             {
0840 
0841                 NDRX_LOG(log_error, "(%s) Invalid prio %d in <services> section min %d max %d", 
0842                     G_sys_config.config_file_short, p_svc->routsvc.prio,
0843                     NDRX_MSGPRIO_MIN, NDRX_MSGPRIO_MAX);
0844 
0845                 NDRXD_set_error_fmt(NDRXD_ECFGINVLD,
0846                     "(%s) Invalid prio %d in <services> section min %d max %d near line %d",    
0847                     G_sys_config.config_file_short, p_svc->routsvc.prio,
0848                     NDRX_MSGPRIO_MIN, NDRX_MSGPRIO_MAX, G_sys_config.last_line);
0849 
0850                 xmlFree(p);
0851                 EXFAIL_OUT(ret);
0852             }
0853         }
0854         else if (0==strcmp((char *)attr->name, "routing"))
0855         {
0856             
0857             /* for debug purposes have criterion too
0858              * also if criterion is missing
0859              * we do not need to do routing
0860              */
0861             NDRX_STRCPY_SAFE(p_svc->routsvc.criterion, p);
0862         }
0863         else if (0==strcmp((char *)attr->name, "autotran"))
0864         {
0865             /* y/Y */
0866             if (NDRX_SETTING_TRUE1==*p || NDRX_SETTING_TRUE2==*p)
0867             {
0868                 p_svc->routsvc.autotran=EXTRUE;
0869             } /* n/N - Bug #675 */
0870             else if (NDRX_SETTING_FALSE1==*p || NDRX_SETTING_FALSE1==*p)
0871             {
0872                 p_svc->routsvc.autotran=EXFALSE;
0873             }
0874             else
0875             {
0876                 NDRX_LOG(log_error, "(%s) Invalid autotran setting [%s] in <services> "
0877                         "section, expected values [%c%c%c%c]", 
0878                         G_sys_config.config_file_short, p,
0879                         NDRX_SETTING_TRUE1, NDRX_SETTING_TRUE2,
0880                         NDRX_SETTING_FALSE1, NDRX_SETTING_FALSE2);
0881                 NDRXD_set_error_fmt(NDRXD_ECFGINVLD,
0882                     "(%s) Invalid autotran setting [%s] in <services> "
0883                         "section, expected values [%c%c%c%c] near line %d", 
0884                         G_sys_config.config_file_short, p,
0885                         NDRX_SETTING_TRUE1, NDRX_SETTING_TRUE2,
0886                         NDRX_SETTING_FALSE1, NDRX_SETTING_FALSE2,
0887                         G_sys_config.last_line);
0888 
0889                 xmlFree(p);
0890                 EXFAIL_OUT(ret);
0891             }
0892         }
0893         else if (0==strcmp((char *)attr->name, "trantime"))
0894         {
0895             p_svc->routsvc.trantime = atol(p);
0896         }
0897         
0898         xmlFree(p);
0899     }
0900     
0901         /* no hashing for defaults */
0902     if (!is_defaults)
0903     {
0904         /* Check service settings */
0905         if (EXEOS==p_svc->routsvc.svcnm[0])
0906         {
0907             NDRX_LOG(log_error, "(%s) Empty service definition", 
0908                     G_sys_config.config_file_short);
0909 
0910             NDRXD_set_error_fmt(NDRXD_ECFGINVLD, "(%s) Empty service definition near line %d", 
0911                     G_sys_config.config_file_short,
0912                     G_sys_config.last_line);
0913             EXFAIL_OUT(ret);
0914         }
0915     
0916         EXHASH_FIND_STR(config->services, p_svc->routsvc.svcnm, elt);
0917 
0918         if (NULL!=elt)
0919         {
0920             NDRX_LOG(log_error, "(%s) Service [%s] already defined", 
0921                     G_sys_config.config_file_short, p_svc->svcnm);
0922 
0923             NDRXD_set_error_fmt(NDRXD_ECFGINVLD, "(%s) Service [%s] already defined"
0924                     " near line %d", 
0925                     G_sys_config.config_file_short,p_svc->svcnm, G_sys_config.last_line);
0926             EXFAIL_OUT(ret);
0927         }
0928 
0929         NDRX_LOG(log_debug, "SERVICES Entry: SVCNM=%s PRIO=%d ROUTING=%s AUTOTRAN=%c TRANTIME=%lu",
0930                 p_svc->routsvc.svcnm, p_svc->routsvc.prio, p_svc->routsvc.criterion, 
0931                 p_svc->routsvc.autotran?'Y':'N', p_svc->routsvc.trantime);
0932 
0933         EXHASH_ADD_STR(config->services, svcnm, p_svc);
0934     }
0935 out:
0936     
0937     /* defaults are static..  */
0938     if (EXFAIL==ret && !is_defaults && p_svc)
0939     {
0940         NDRX_FREE(p_svc);
0941     }
0942     return ret;
0943 }
0944 
0945 /**
0946  * Parse routing
0947  */
0948 expublic int ndrx_services_parse(config_t *config, xmlDocPtr doc, xmlNodePtr cur)
0949 {
0950     int ret=EXSUCCEED;
0951     ndrx_services_hash_t default_svc;
0952     
0953     int is_service;
0954     int is_defaults;
0955     
0956     memset(&default_svc, 0, sizeof(default_svc));
0957     
0958         /* set default prio */
0959     default_svc.routsvc.prio = NDRX_MSGPRIO_DEFAULT;
0960     default_svc.routsvc.trantime = NDRX_DDR_TRANTIMEDFLT;
0961     
0962     for (; cur ; cur=cur->next)
0963     {
0964         is_service= (0==strcmp((char*)cur->name, "service"));
0965         is_defaults= (0==strcmp((char*)cur->name, "defaults"));
0966         G_sys_config.last_line = cur->line;
0967         
0968         if (is_service || is_defaults)
0969         {
0970             /* Get the server name */
0971             if (EXSUCCEED!=ndrx_service_parse(config, doc, cur, is_defaults, &default_svc))
0972             {
0973                 NDRXD_set_error_fmt(NDRXD_ECFGINVLD, "(%s) Failed to "
0974                         "parse <service> section near line %d", 
0975                         G_sys_config.config_file_short, G_sys_config.last_line);
0976                 ret=EXFAIL;
0977                 goto out;
0978             }
0979         }
0980     }
0981 out:
0982                 
0983     return ret;
0984 }
0985 
0986 /**
0987  * Free services if any found in config object
0988  * @param config config object
0989  */
0990 expublic void ndrx_services_free(config_t *config)
0991 {
0992     ndrx_services_hash_t *el, *elt;
0993     
0994     EXHASH_ITER(hh, config->services, el, elt)
0995     {
0996         EXHASH_DEL(config->services, el);
0997         NDRX_FREE(el);
0998     }
0999 }
1000 
1001 /**
1002  * Free up route criterion
1003  * @param p_crit allocd object
1004  */
1005 exprivate void ndrx_routcrit_type_free(ndrx_routcrit_typehash_t *o_type)
1006 {
1007      ndrx_routcritseq_dl_t *el, *elt;
1008     
1009     if (NULL!=o_type->ranges)
1010     {
1011         NDRX_FREE(o_type->ranges);
1012     }
1013      
1014     /* clean up the DL */
1015     DL_FOREACH_SAFE(o_type->seq, el, elt)
1016     {
1017         DL_DELETE(o_type->seq, el);
1018         NDRX_FREE(el);
1019     }
1020 
1021     NDRX_FREE(o_type);
1022 }
1023 
1024 /**
1025  * Free up all routcrit elements
1026  * @param config config to free up
1027  */
1028 exprivate void ndrx_routcrit_free(config_t *config)
1029 {
1030     ndrx_routcrit_hash_t *el, *elt;
1031     ndrx_routcrit_typehash_t *t, *tt;
1032     
1033     /* remove all routes */
1034     EXHASH_ITER(hh, config->cirthash, el, elt)
1035     {
1036         
1037         /* remove all types */
1038         EXHASH_ITER(hh, el->btypes, t, tt)
1039         {
1040             
1041             EXHASH_DEL(el->btypes, t);
1042             ndrx_routcrit_type_free(t);
1043         }
1044         
1045         EXHASH_DEL(config->cirthash, el);
1046         NDRX_FREE(el);
1047     }
1048 }
1049 
1050 /**
1051  * Free up all routing structs
1052  * including allocated work blocks for generating the layout
1053  * @param p_crit
1054  */
1055 expublic void ndrx_ddr_free_all(config_t *config)
1056 {
1057     if (NULL!=config->services_block)
1058     {
1059         NDRX_FREE(config->services_block);
1060     }
1061     
1062     if (NULL!=config->routing_block)
1063     {
1064         NDRX_FREE(config->routing_block);
1065     }
1066     
1067     /* free up the temporary lists */
1068     ndrx_services_free(config);
1069     config->services=NULL;
1070     
1071     ndrx_routcrit_free(config);
1072     config->cirthash=NULL;
1073 }
1074 
1075 /**
1076  * Load the routing
1077  * @param mem memory segment start
1078  * @param size of the segment
1079  * @param routes
1080  * @return EXSUCCEED/EXFAIL
1081  */
1082 expublic int ndrx_ddr_criterion_put(char *mem, long size, ndrx_routcrit_hash_t *routes)
1083 {
1084     ndrx_routcrit_hash_t *el, *elt;
1085     ndrx_routcrit_typehash_t *t, *tt;
1086     ndrx_routcritseq_dl_t *dl;
1087     int block_size;
1088     int critid = 1;
1089     long pos=0;
1090     long size_left = size;
1091     int org_len;
1092     int ret = EXSUCCEED;
1093     ndrx_routcrit_t *p_crit;
1094     
1095     EXHASH_ITER(hh, routes, el, elt)
1096     {
1097         /* assign for later quick lookup */
1098         el->criterionid = critid;
1099         
1100         /* this is where criterion starts, for quick lookup  */
1101         el->offset = pos;
1102     
1103         EXHASH_ITER(hh, el->btypes, t, tt)
1104         {
1105             t->routcrit.criterionid=critid;
1106             /* this shall be already aligned */
1107             block_size = sizeof(t->routcrit);
1108             
1109             if (block_size>size_left)
1110             {
1111                 /* cannot install block */
1112                 NDRX_LOG(log_error, "(%s) Cannot install route [%s] type [%s] "
1113                         "block. %s too small (block size %d pos %ld size %ld)", 
1114                         G_sys_config.config_file_short, el->criterion, t->buftype, 
1115                         CONF_NDRX_RTCRTMAX, block_size, pos, size);
1116                 NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Cannot install route [%s] type [%s] "
1117                         "block. %s too small (block size %d pos %ld size %ld)", 
1118                         G_sys_config.config_file_short, el->criterion, t->buftype, 
1119                         CONF_NDRX_RTCRTMAX, block_size, pos, size);
1120                 EXFAIL_OUT(ret);
1121             }
1122             
1123             memcpy(mem+pos, &t->routcrit, block_size);
1124             
1125             p_crit = (ndrx_routcrit_t *)(mem+pos);
1126             p_crit->len = sizeof(ndrx_routcrit_t);
1127             
1128             pos+=block_size;
1129             size_left-=block_size;
1130             
1131             /* process now ranges */
1132             DL_FOREACH(t->seq, dl)
1133             {
1134                 org_len=dl->cseq.len;
1135                 dl->cseq.len = DDR_ALIGNED_GEN(dl->cseq.len);
1136                 block_size = dl->cseq.len;
1137                 
1138                 p_crit->len+=block_size;
1139                 
1140                 NDRX_LOG(log_debug, "Range Block size %ld", block_size);
1141                 
1142                 if (block_size>size_left)
1143                 {
1144                     /* cannot install block */
1145                     NDRX_LOG(log_error, "(%s) Cannot install route seq [%s] type [%s] block. %s too small", 
1146                             G_sys_config.config_file_short, el->criterion, t->buftype, CONF_NDRX_RTCRTMAX);
1147                     NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Cannot install route seq [%s] type [%s] block. %s too small", 
1148                             G_sys_config.config_file_short, el->criterion, t->buftype, CONF_NDRX_RTCRTMAX);
1149                     EXFAIL_OUT(ret);
1150                 }
1151                 
1152                 memcpy(mem+pos, &dl->cseq, org_len);
1153                 pos+=block_size;
1154                 size_left-=block_size;
1155             }
1156         }
1157         critid++;
1158     }
1159     
1160 out:
1161     return ret;
1162 }
1163 
1164 /**
1165  * - We need to populate the memory block with services (use standard
1166  *  linear hashing routines)
1167  * - Also... needs to populate the memory block routes
1168  *  use custom TLV build.
1169  * @param config generate blocks
1170  * @return EXSUCCEED/EXFAIL
1171  */
1172 expublic int ndrx_ddr_gen_blocks(config_t *config)
1173 {
1174     int ret = EXSUCCEED;
1175     ndrx_services_hash_t *el, *elt;
1176     ndrx_routcrit_hash_t *rt;
1177     /* loop over all routing blocks
1178      * and calculate the mem & updates offset for the criterion start
1179      */
1180     
1181     config->routing_block = NDRX_CALLOC(G_atmi_env.rtcrtmax, 1);
1182     
1183     if (NULL==config->routing_block)
1184     {
1185         NDRX_LOG(log_error, "(%s) Failed to malloc %d bytes (routing_block)", 
1186                 G_sys_config.config_file_short, G_atmi_env.rtcrtmax);
1187         NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Failed to malloc %d bytes (routing_block)",
1188                 G_sys_config.config_file_short, G_atmi_env.rtcrtmax);
1189         EXFAIL_OUT(ret);
1190     }
1191     
1192     if (EXSUCCEED!=ndrx_ddr_criterion_put(config->routing_block, G_atmi_env.rtcrtmax, 
1193             config->cirthash))
1194     {
1195         EXFAIL_OUT(ret);
1196     }
1197     
1198     /* loop over services - lookup the criterion start
1199      * update the and write to memory block
1200      * We need hashing for services.
1201      * Check if criterion needs to be checked or not
1202      */
1203     config->services_block = NDRX_CALLOC(sizeof(ndrx_services_t)*G_atmi_env.rtsvcmax, 1);
1204     
1205     if (NULL==config->services_block)
1206     {
1207         NDRX_LOG(log_error, "(%s) Failed to malloc %d bytes (services_block)", 
1208                 G_sys_config.config_file_short, sizeof(ndrx_services_t)*G_atmi_env.rtsvcmax);
1209         NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Failed to malloc %d bytes (services_block)",
1210                 G_sys_config.config_file_short, sizeof(ndrx_services_t)*G_atmi_env.rtsvcmax);
1211         EXFAIL_OUT(ret);
1212     }
1213     
1214     EXHASH_ITER(hh, config->services, el, elt)
1215     {
1216         
1217         if (EXEOS!=el->routsvc.criterion[0])
1218         {    
1219             /* lookup criterion here & get offset
1220              * also check if criterion is missing, in such case generate error
1221              */
1222             EXHASH_FIND_STR(config->cirthash, el->routsvc.criterion, rt);
1223             
1224             if (NULL==rt)
1225             {
1226                 NDRX_LOG(log_error, "(%s) Service [%s] routing criterion [%s] not defined", 
1227                     G_sys_config.config_file_short, el->routsvc.svcnm, el->routsvc.criterion);
1228                 NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Service [%s] routing criterion [%s] not defined", 
1229                     G_sys_config.config_file_short, el->routsvc.svcnm, el->routsvc.criterion);
1230                 EXFAIL_OUT(ret);
1231             }
1232             el->routsvc.offset=rt->offset;
1233             el->routsvc.cirterionid =rt->criterionid;
1234         }
1235         /* else it is just infos for auto-transactions/timeouts and priority... */
1236         
1237         NDRX_LOG(log_debug, "Installing routing service [%s]", el->routsvc.svcnm);
1238         if (EXSUCCEED!=ndrx_ddr_services_put(&el->routsvc, config->services_block, G_atmi_env.rtsvcmax))
1239         {
1240             NDRX_LOG(log_error, "(%s) Failed to put service config [%s] into memory, check %s size", 
1241                 G_sys_config.config_file_short, el->routsvc.svcnm, CONF_NDRX_RTSVCMAX);
1242             NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Failed to put service config [%s] into memory, check %s size", 
1243                 G_sys_config.config_file_short, el->routsvc.svcnm, CONF_NDRX_RTSVCMAX);
1244             EXFAIL_OUT(ret);
1245         }
1246     }
1247     
1248 out:
1249     return ret;
1250 }
1251 
1252 /**
1253  * Parse single route entry.
1254  * @param config current config loading
1255  * @param doc
1256  * @param cur
1257  * @return EXSUCCEED/EXFAIL
1258  */
1259 expublic int ndrx_route_parse(config_t *config, xmlDocPtr doc, xmlNodePtr cur)
1260 {
1261     int ret=EXSUCCEED;
1262     int len;
1263     xmlAttrPtr attr;
1264     ndrx_routcrit_hash_t *p_route=NULL;
1265     ndrx_routcrit_typehash_t *p_crit=NULL;
1266     ndrx_routcrit_typehash_t *el=NULL;
1267     char *p;
1268     int i;
1269     typed_buffer_descr_t *descr;
1270     struct
1271     {
1272         char *typecode;
1273         int typeid;
1274     } typemap [] = {
1275 
1276         {"CHAR",  BFLD_CHAR},
1277         {"SHORT", BFLD_SHORT},
1278         {"LONG",  BFLD_LONG},
1279         {"FLOAT", BFLD_FLOAT},
1280         {"DOUBLE",BFLD_DOUBLE},
1281         {"STRING",BFLD_STRING}
1282     };
1283     
1284     for (attr=cur->properties; attr; attr = attr->next)
1285     {
1286         p = (char *)xmlNodeGetContent(attr->children);
1287            
1288         if (0==strcmp((char *)attr->name, "routing"))
1289         {
1290             if (NULL==(p_route = ndrx_criterion_get(config, p)))
1291             {
1292                 xmlFree(p);
1293                 EXFAIL_OUT(ret);
1294             }
1295         }
1296         
1297         xmlFree(p);
1298     }
1299     
1300     if (NULL==p_route)
1301     {
1302         NDRX_LOG(log_error, "(%s) Missing `routing' attribute",
1303                 G_sys_config.config_file_short);
1304         NDRXD_set_error_fmt(NDRXD_ECFGINVLD, "(%s) Missing `routing' attribute"
1305                 " near line %d",
1306                 G_sys_config.config_file_short, G_sys_config.last_line);
1307         EXFAIL_OUT(ret);
1308     }
1309     
1310     /* allocate criterion, so that we have place to work */
1311     p_crit = NDRX_MALLOC(sizeof(*p_crit)); 
1312     
1313     if (NULL==p_crit)
1314     {
1315         NDRX_LOG(log_error, "(%s) Failed to malloc %d bytes", 
1316                 G_sys_config.config_file_short, *p_crit);
1317         NDRXD_set_error_fmt(NDRXD_EOS, "(%s) Failed to malloc %d bytes"
1318                 " near line %d",
1319                 G_sys_config.config_file_short, *p_crit,
1320                 G_sys_config.last_line);
1321         goto out;
1322     }
1323     
1324     memset(p_crit, 0, sizeof(*p_crit));
1325     
1326     p_crit->routcrit.fieldtypeid=EXFAIL;
1327     p_crit->routcrit.buffer_type_id=EXFAIL;
1328     NDRX_STRCPY_SAFE(p_crit->routcrit.criterion, p_route->criterion);
1329     
1330     
1331     /* Now grab the all stuff for server */
1332     cur=cur->children;
1333     for (; cur; cur=cur->next)
1334     {
1335         G_sys_config.last_line=cur->line;
1336         p = (char *)xmlNodeGetContent(cur);
1337         
1338         if (0==strcmp("field", (char *)cur->name))
1339         {
1340             NDRX_STRCPY_SAFE(p_crit->routcrit.field, p);
1341         }
1342         else if (0==strcmp("ranges", (char *)cur->name))
1343         {
1344             if (NULL!=p_crit->ranges)
1345             {
1346                 NDRX_LOG(log_error, "(%s) <ranges> already loaded for route [%s]", 
1347                         G_sys_config.config_file_short, p_crit->routcrit.criterion);
1348                 NDRXD_set_error_fmt(NDRXD_ECFGINVLD, "(%s) <ranges> already loaded for route [%s]"
1349                         " near line %d", 
1350                         G_sys_config.config_file_short, p_crit->routcrit.criterion,
1351                         G_sys_config.last_line);
1352                 xmlFree(p);
1353                 EXFAIL_OUT(ret);
1354             }
1355             
1356             p_crit->ranges=NDRX_STRDUP(p);
1357             if (NULL==p_crit->ranges)
1358             {
1359                 len = strlen(p);
1360                 NDRX_LOG(log_error, "(%s) Failed to malloc %d bytes", 
1361                         G_sys_config.config_file_short, len);
1362                 NDRXD_set_error_fmt(NDRXD_EOS, "(%s) Failed to malloc %d bytes",
1363                         G_sys_config.config_file_short, len);
1364                 xmlFree(p);
1365                 EXFAIL_OUT(ret);
1366             }
1367         }
1368         else if (0==strcmp("buftype", (char *)cur->name))
1369         {
1370             /* Resolve type -> currently only UBF/ supported 
1371              * Thus we do not check the sub-types
1372              * Probably in future if we support view, then on the fly string
1373              * needs to be scanned with substr for the view/field.
1374              */
1375             descr=ndrx_get_buffer_descr(p, NULL);
1376             
1377             if (NULL==descr || BUF_TYPE_UBF!=descr->type_id)
1378             {
1379                 NDRX_LOG(log_error, "(%s) Invalid <routing> buftype [%s]",
1380                         G_sys_config.config_file_short, p);
1381                 NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Invalid <routing> buftype [%s]"
1382                         " near line %d",
1383                         G_sys_config.config_file_short, p,
1384                         G_sys_config.last_line);
1385                 xmlFree(p);
1386                 EXFAIL_OUT(ret);
1387             }
1388             
1389             NDRX_STRCPY_SAFE(p_crit->routcrit.buftype, p);
1390             NDRX_STRCPY_SAFE(p_crit->buftype, p);
1391             p_crit->routcrit.buffer_type_id = descr->type_id;
1392             
1393             /* Check that this type range is not already allocated */
1394             EXHASH_FIND_STR(p_route->btypes, p, el);
1395             
1396             if (NULL!=el)
1397             {
1398                 NDRX_LOG(log_error, "(%s) Buffer type [%s] already defined for route [%s]",
1399                         G_sys_config.config_file_short, p, p_route->criterion);
1400                 NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Buffer type [%s] already defined for route [%s]"
1401                         " near line %d",
1402                         G_sys_config.config_file_short, p, p_route->criterion,
1403                         G_sys_config.last_line);
1404                 xmlFree(p);
1405                 EXFAIL_OUT(ret);
1406             }   
1407             
1408         }
1409         else if (0==strcmp("fieldtype", (char *)cur->name))
1410         {
1411             /* This is field type according to which we plan to route 
1412              */
1413             for (i=0; i<N_DIM(typemap); i++)
1414             {
1415                 if (0==strcmp(typemap[i].typecode, p))
1416                 {
1417                     p_crit->routcrit.fieldtypeid = typemap[i].typeid;
1418                     break;
1419                 }
1420             }
1421             
1422             if (EXFAIL==p_crit->routcrit.fieldtypeid)
1423             {
1424                 NDRX_LOG(log_error, "(%s) Invalid field type [%s]",
1425                         G_sys_config.config_file_short, p);
1426                 NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Invalid field type [%s]"
1427                         " near line %d",
1428                         G_sys_config.config_file_short, p,
1429                         G_sys_config.last_line);
1430                 xmlFree(p);
1431                 EXFAIL_OUT(ret);
1432             }
1433         }
1434         
1435         xmlFree(p);
1436     }
1437 
1438     /* Resolve field & type 
1439      * Maybe in future we want to move this configuation to per buffer type
1440      * callbacks.
1441      */
1442     if (BUF_TYPE_UBF==p_crit->routcrit.buffer_type_id)
1443     {
1444         
1445         p_crit->routcrit.fldid = Bfldid(p_crit->routcrit.field);
1446         
1447         if (BBADFLDID==p_crit->routcrit.fldid)
1448         {
1449             NDRX_LOG(log_error, "(%s) Invalid routing field [%s] for route [%s]",
1450                         G_sys_config.config_file_short, 
1451                     p_crit->routcrit.field, p_route->criterion);
1452             NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Invalid routing field [%s] for route [%s]"
1453                     " near line %d",
1454                     G_sys_config.config_file_short, 
1455                     p_crit->routcrit.field, p_route->criterion,
1456                     G_sys_config.last_line);
1457             EXFAIL_OUT(ret);
1458         }
1459         
1460         /* if we go the field then type  */
1461         
1462         /* detect the routing type at which we plan to work */
1463         if (EXFAIL==p_crit->routcrit.fieldtypeid)
1464         {
1465             p_crit->routcrit.fieldtypeid = Bfldtype(p_crit->routcrit.fldid);
1466             
1467             if (EXFAIL==p_crit->routcrit.fieldtypeid)
1468             {
1469                 NDRX_LOG(log_error, "(%s) Failed to detect field type [%s]: %s",
1470                             G_sys_config.config_file_short, 
1471                         p_crit->routcrit.field, Bstrerror(Berror));
1472                 NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Failed to detect field type [%s]: %s"
1473                         " near line %d",
1474                         G_sys_config.config_file_short, 
1475                         p_crit->routcrit.field, Bstrerror(Berror),
1476                         G_sys_config.last_line);
1477                 EXFAIL_OUT(ret);
1478             }
1479         }
1480         
1481         /* configure route type... */
1482         
1483         if (BFLD_SHORT == p_crit->routcrit.fieldtypeid
1484                 || BFLD_LONG == p_crit->routcrit.fieldtypeid
1485                 )
1486         {
1487             p_crit->routcrit.fieldtypeid = BFLD_LONG;
1488         }
1489         else if (BFLD_FLOAT == p_crit->routcrit.fieldtypeid
1490                 || BFLD_DOUBLE == p_crit->routcrit.fieldtypeid
1491                 )
1492         {
1493             p_crit->routcrit.fieldtypeid = BFLD_DOUBLE;
1494         }
1495         else if (BFLD_STRING == p_crit->routcrit.fieldtypeid
1496                 || BFLD_CARRAY == p_crit->routcrit.fieldtypeid
1497                 || BFLD_CHAR == p_crit->routcrit.fieldtypeid
1498                 )
1499         {
1500             p_crit->routcrit.fieldtypeid = BFLD_STRING;
1501         }
1502         else
1503         {
1504             NDRX_LOG(log_error, "(%s) Unroutable UBF field [%s] type [%s] (%d)",
1505                             G_sys_config.config_file_short, 
1506                             p_crit->routcrit.field, Btype(p_crit->routcrit.fldid),
1507                             p_crit->routcrit.fieldtypeid);
1508             NDRXD_set_error_fmt(NDRXD_EINVAL, "(%s) Unroutable UBF field [%s] type [%s] (%d)"
1509                             " near line %d",
1510                             G_sys_config.config_file_short, 
1511                             p_crit->routcrit.field, Btype(p_crit->routcrit.fldid),
1512                             p_crit->routcrit.fieldtypeid,
1513                             G_sys_config.last_line);
1514             EXFAIL_OUT(ret);
1515         }
1516     }
1517     
1518     /* parse the ranges, either range is string based
1519      * or range is float based
1520      */
1521     
1522     if (EXSUCCEED!=ndrx_parse_range(p_crit))
1523     {
1524         NDRX_LOG(log_error, "Failed to parse range");
1525         EXFAIL_OUT(ret);
1526     }
1527     
1528     
1529     NDRX_LOG(log_debug, "--- Adding Route [%s] range ---", p_route->criterion);
1530     
1531     
1532     NDRX_LOG(log_debug, "criterion: [%s]", p_crit->routcrit.criterion);
1533     
1534     NDRX_LOG(log_debug, "criterionid: [%d]", p_crit->routcrit.criterionid);
1535     NDRX_LOG(log_debug, "len: [%d]", p_crit->routcrit.len);
1536     NDRX_LOG(log_debug, "field: [%s]", p_crit->routcrit.field);
1537     NDRX_LOG(log_debug, "buffer_type_id: [%hd]", p_crit->routcrit.buffer_type_id);
1538     NDRX_LOG(log_debug, "buftype: [%s]", p_crit->routcrit.buftype);
1539     NDRX_LOG(log_debug, "fieldtype: [%s]", p_crit->routcrit.fieldtype);
1540     NDRX_LOG(log_debug, "fieldtypeid: [%d]", p_crit->routcrit.fieldtypeid);
1541     NDRX_LOG(log_debug, "fldid: [%d]", p_crit->routcrit.fldid);
1542     NDRX_LOG(log_debug, "rangesnr: [%ld]", p_crit->routcrit.rangesnr);
1543     
1544     NDRX_LOG(log_debug, "-------------------------------------");
1545     
1546     /* if parsed ok, add to type hash, not ?  */
1547     EXHASH_ADD_STR(p_route->btypes, buftype, p_crit);
1548     
1549 out:
1550 
1551     if (EXSUCCEED!=ret && NULL!=p_crit)
1552     {
1553         ndrx_routcrit_type_free(p_crit);
1554     
1555     }
1556                 
1557     return ret;
1558 }
1559 
1560 
1561 /**
1562  * Parse routing entry
1563  * @param config config in progress
1564  * @param doc
1565  * @param cur
1566  * @return 
1567  */
1568 expublic int ndrx_routing_parse(config_t *config, xmlDocPtr doc, xmlNodePtr cur)
1569 {
1570     int ret=EXSUCCEED;
1571     
1572     for (; cur ; cur=cur->next)
1573     {
1574         G_sys_config.last_line = cur->line;
1575         if (0==strcmp((char*)cur->name, "route"))
1576         {
1577             /* Get the server name */
1578             if (EXSUCCEED!=ndrx_route_parse(config, doc, cur))
1579             {
1580                 NDRXD_set_error_fmt(NDRXD_ECFGINVLD, "(%s) Failed to "
1581                         "parse <route> section near line %d", 
1582                         G_sys_config.config_file_short, G_sys_config.last_line);
1583                 ret=EXFAIL;
1584                 goto out;
1585             }
1586         }
1587     }
1588 out:
1589     return ret;
1590 }
1591 
1592 /* vim: set ts=4 sw=4 et smartindent: */