Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Field database support routines
0003  *
0004  * @file fielddb.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 <string.h>
0037 #include <ubf_int.h>
0038 #include <stdlib.h>
0039 #include <errno.h>
0040 
0041 #include <tperror.h>
0042 #include <fieldtable.h>
0043 #include <fdatatype.h>
0044 #include <ferror.h>
0045 #include <utlist.h>
0046 
0047 #include "ndebug.h"
0048 #include "ubf_tls.h"
0049 #include "cconfig.h"
0050 #include "expr.h"
0051 #include <ubfdb.h>
0052 #include <edbutil.h>
0053 /*---------------------------Externs------------------------------------*/
0054 /*---------------------------Macros-------------------------------------*/
0055 /*---------------------------Enums--------------------------------------*/
0056 /*---------------------------Typedefs-----------------------------------*/
0057 /*---------------------------Globals------------------------------------*/
0058 expublic int ndrx_G_ubf_db_triedload = EXFALSE; /* Have we tried to load? */
0059 /* If NULL and tried, then no db defined  */
0060 expublic ndrx_ubf_db_t * ndrx_G_ubf_db = NULL;
0061 
0062 /* have some thread safety here */
0063 exprivate MUTEX_LOCKDECL(M_ubdb_init);
0064 
0065 /*---------------------------Statics------------------------------------*/
0066 /*---------------------------Prototypes---------------------------------*/
0067 
0068 /**
0069  * Map DB error
0070  * @param unixerr unix error
0071  * @return UBF error
0072  */
0073 expublic int ndrx_ubfdb_maperr(int unixerr)
0074 {
0075     int ret = BEUNIX;
0076     
0077     switch (unixerr)
0078     {
0079         case EDB_NOTFOUND:
0080             
0081             ret = BBADFLD;
0082             break;
0083         case EDB_MAP_FULL:
0084         case EDB_DBS_FULL:
0085         case EDB_READERS_FULL:
0086         case EDB_TLS_FULL:
0087         case EDB_TXN_FULL:
0088         case EDB_CURSOR_FULL:
0089         case EDB_PAGE_FULL:
0090             ret = BNOSPACE;
0091             break;
0092     }
0093     
0094     return ret;
0095 }
0096 
0097 /**
0098  * Load database of fields
0099  * 
0100  * @return -1 EXFAIL, 0 -> no DB defined, 1 -> DB defined and loaded
0101  */
0102 expublic int ndrx_ubfdb_Bflddbload(void)
0103 {
0104     int ret = EXSUCCEED;
0105     int any_config=EXFALSE;
0106     int tran_started = EXFALSE;
0107     EDB_txn *txn = NULL;
0108     ndrx_inicfg_section_keyval_t * csection = NULL, *val = NULL, *val_tmp = NULL;
0109     
0110     MUTEX_LOCK_V(M_ubdb_init);
0111     
0112     if (NULL!=ndrx_G_ubf_db)
0113     {
0114         UBF_LOG(log_warn, "UBF DB already loaded!");
0115         goto out;
0116     }
0117     
0118     /* might be already loaded - no problem, it is singleton */
0119     if (EXSUCCEED!=(ret=ndrx_cconfig_load()))
0120     {
0121         ndrx_Bset_error_fmt(BEUNIX, "%s: Failed to load common-config (CC)",
0122                 __func__);
0123         
0124         UBF_LOG(log_error, "Failed to load Common config!");
0125         goto out;
0126     }
0127     
0128     if (NULL==ndrx_get_G_cconfig())
0129     {
0130         UBF_LOG(log_info, "Common Config not defined - nothing to do!");
0131         goto out;
0132     }
0133     
0134     if (EXSUCCEED!=ndrx_cconfig_get(NDRX_CONF_SECTION_UBFDB, &csection))
0135     {
0136         UBF_LOG(log_debug, "UBF DB not defined");
0137         goto out;
0138     }
0139 
0140     if (NULL==ndrx_G_ubf_db)
0141     {
0142         if (NULL==(ndrx_G_ubf_db = NDRX_CALLOC(1, sizeof(ndrx_ubf_db_t))))
0143         {
0144             int err = errno;
0145             UBF_LOG(log_error, "%s: Failed to alloc %d bytes: %s",
0146                         __func__, sizeof(ndrx_ubf_db_t), strerror(err));
0147 
0148             ndrx_Bset_error_fmt(BMALLOC, "%s: Failed to alloc %d bytes: %s",
0149                         __func__, sizeof(ndrx_ubf_db_t), strerror(err));
0150 
0151             userlog("%s: Failed to alloc %d bytes: %s",
0152                         __func__, sizeof(ndrx_ubf_db_t), strerror(err));
0153             EXFAIL_OUT(ret);
0154         }
0155     }
0156     
0157     /* loop over the config... */
0158     ndrx_G_ubf_db->max_readers = NDRX_UBFDB_MAX_READERS_DFLT;
0159     ndrx_G_ubf_db->map_size = NDRX_UBFDB_MAP_SIZE_DFLT;
0160     ndrx_G_ubf_db->perms = NDRX_UBFDB_PERMS_DFLT;
0161     
0162     EXHASH_ITER(hh, csection, val, val_tmp)
0163     {
0164         any_config = EXTRUE;
0165 
0166         UBF_LOG(log_debug, "%s: config: key: [%s] value: [%s]",
0167                     __func__, val->key, val->val);
0168         
0169         if (0==strcmp(val->key, NDRX_UBFDB_KWD_RESOURCE))
0170         {
0171             NDRX_STRCPY_SAFE(ndrx_G_ubf_db->resource, val->val);
0172         }
0173         else if (0==strcmp(val->key, NDRX_UBFDB_KWD_PERMS))
0174         {
0175             char *pend;
0176             ndrx_G_ubf_db->perms = strtol(val->val, &pend, 0);
0177         }
0178         /* Also float: Parse 1000, 1K, 1M, 1G */
0179         else if (0==strcmp(val->key, NDRX_UBFDB_KWD_MAX_READERS))
0180         {
0181             ndrx_G_ubf_db->max_readers = (long)ndrx_num_dec_parsecfg(val->val);
0182         }
0183         /* Parse float: 1000.5, 1.2K, 1M, 1G */
0184         else if (0==strcmp(val->key, NDRX_UBFDB_KWD_MAP_SIZE))
0185         {
0186             ndrx_G_ubf_db->map_size = (long)ndrx_num_dec_parsecfg(val->val);
0187         }
0188         else
0189         {
0190             UBF_LOG(log_warn, "Ignoring unknown cache configuration param: [%s]", 
0191                     val->key);
0192             userlog("Ignoring unknown cache configuration param: [%s]", 
0193                     val->key);
0194         }
0195     }
0196     
0197     if (!any_config)
0198     {
0199         NDRX_FREE(ndrx_G_ubf_db);
0200         ndrx_G_ubf_db=NULL;
0201         UBF_LOG(log_info, "%s: no [%s] section defined - nothing to do!",
0202                 __func__, NDRX_CONF_SECTION_UBFDB);
0203         goto out;
0204     }
0205     
0206     if (EXEOS==ndrx_G_ubf_db->resource[0])
0207     {
0208         NDRX_UBFDB_BERROR(BEINVAL, 
0209                 "%s: [%s] attrib is missing for [%s] section!", 
0210                 __func__, NDRX_UBFDB_KWD_RESOURCE, NDRX_CONF_SECTION_UBFDB);
0211         EXFAIL_OUT(ret);
0212     }
0213  
0214     NDRX_UBFDB_DUMPCFG(log_debug, ndrx_G_ubf_db);
0215     
0216     if (EXSUCCEED!=(ret=edb_env_create(&ndrx_G_ubf_db->env)))
0217     {
0218         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0219                 "%s: Failed to create env for UBF table DB: %s", 
0220                 __func__, edb_strerror(errno));
0221         EXFAIL_OUT(ret);
0222     }
0223     
0224     if (EXSUCCEED!=(ret=edb_env_set_maxreaders(ndrx_G_ubf_db->env, 
0225             ndrx_G_ubf_db->max_readers)))
0226     {
0227         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0228                 "%s: Failed to set max readers for ubf db: %s", 
0229                 __func__, edb_strerror(ret));
0230         
0231         EXFAIL_OUT(ret);
0232     }
0233 
0234     if (EXSUCCEED!=(ret=edb_env_set_maxdbs(ndrx_G_ubf_db->env, 2)))
0235     {
0236         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0237                 "%s: Failed to set max dbs for ubf db: %s", 
0238                 __func__, edb_strerror(ret));
0239         
0240         EXFAIL_OUT(ret);
0241     }
0242     
0243     if (EXSUCCEED!=(ret=edb_env_set_mapsize(ndrx_G_ubf_db->env, 
0244             ndrx_G_ubf_db->map_size)))
0245     {
0246         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0247                 "%s: Failed to set map size for ubf db: %s", 
0248                 __func__, edb_strerror(ret));
0249         
0250         EXFAIL_OUT(ret);
0251     }
0252     
0253     if (EXSUCCEED!=(ret=edb_env_open(ndrx_G_ubf_db->env, ndrx_G_ubf_db->resource, 
0254             0, ndrx_G_ubf_db->perms)))
0255     {
0256         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0257                 "%s: Failed to open env for resource [%s]: %s", 
0258                 __func__, ndrx_G_ubf_db->resource, edb_strerror(ret));
0259         
0260         EXFAIL_OUT(ret);
0261     }
0262     
0263     /* Prepare the DB */
0264     if (EXSUCCEED!=(ret=edb_txn_begin(ndrx_G_ubf_db->env, NULL, 0, &txn)))
0265     {
0266         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0267                 "%s: Failed to begin transaction for ubf db: %s", 
0268                 __func__, edb_strerror(ret));
0269         
0270         EXFAIL_OUT(ret);
0271     }
0272     tran_started = EXTRUE;
0273     
0274     /* name database */
0275     if (EXSUCCEED!=(ret=edb_dbi_open(txn, "nm", EDB_CREATE, &ndrx_G_ubf_db->dbi_nm)))
0276     {
0277         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0278                 "%s: Failed to open named db for ubf db: %s", 
0279                 __func__, edb_strerror(ret));
0280         
0281         EXFAIL_OUT(ret);
0282     }
0283     
0284     /* id database */
0285     if (EXSUCCEED!=(ret=edb_dbi_open(txn, "id", EDB_CREATE, &ndrx_G_ubf_db->dbi_id)))
0286     {
0287         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0288                 "%s: Failed to open named id for ubf db: %s", 
0289                 __func__, edb_strerror(ret));
0290         
0291         EXFAIL_OUT(ret);
0292     }
0293     
0294     /* commit the tran */
0295     if (EXSUCCEED!=(ret=edb_txn_commit(txn)))
0296     {
0297         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0298                 "%s: Failed to open named commit: %s", 
0299                 __func__, edb_strerror(ret));
0300         txn = NULL;
0301         EXFAIL_OUT(ret);        
0302     }
0303     
0304     tran_started = EXFALSE;
0305     
0306     
0307 out:
0308 
0309     if (NULL!=csection)
0310     {
0311         ndrx_keyval_hash_free(csection);
0312     }
0313          
0314     if (tran_started)
0315     {
0316         edb_txn_abort(txn);
0317     }
0318 
0319     if (EXSUCCEED!=ret)
0320     {        
0321         if (NULL!=ndrx_G_ubf_db)
0322         {
0323             if (NULL!=ndrx_G_ubf_db->env)
0324             {
0325                 edb_env_close(ndrx_G_ubf_db->env);
0326             }
0327 
0328             NDRX_FREE(ndrx_G_ubf_db);
0329         }
0330         
0331         ndrx_G_ubf_db = NULL;
0332     }
0333 
0334     ndrx_G_ubf_db_triedload=EXTRUE;
0335     
0336     /* return  */
0337     if (EXSUCCEED==ret && NULL!=ndrx_G_ubf_db)
0338     {
0339         MUTEX_UNLOCK_V(M_ubdb_init);
0340         return EXTRUE;
0341     }
0342 
0343     MUTEX_UNLOCK_V(M_ubdb_init);
0344     return ret;
0345 }
0346 
0347 /**
0348  * Add the field to database
0349  * @param txn exdb(lmdb) transaction
0350  * @param fldtype filed id
0351  * @param bfldno field number (not compiled)
0352  * @param fldname field name
0353  * @return EXSUCCEED/EXFAIL
0354  */
0355 expublic int ndrx_ubfdb_Bflddbadd(EDB_txn *txn, 
0356         short fldtype, BFLDID bfldno, char *fldname)
0357 {
0358     int ret = EXSUCCEED;
0359     ndrx_ubfdb_entry_t entry;
0360     BFLDID idcomp = Bmkfldid(fldtype, bfldno);
0361     EDB_val key;
0362     EDB_val data;
0363     
0364     /* prepare data object */
0365     entry.bfldid = idcomp;
0366     NDRX_STRCPY_SAFE(entry.fldname, fldname);
0367     
0368     data.mv_size = sizeof(entry);
0369     data.mv_data = &entry;
0370     
0371     
0372     key.mv_data = &idcomp;
0373     key.mv_size = sizeof(idcomp);
0374     
0375     /* Add ID: */
0376     UBF_LOG(log_debug, "About to put ID record (%d) / [%s]", (int)idcomp, 
0377             entry.fldname);
0378     
0379     if (EXSUCCEED!=(ret=edb_put(txn, ndrx_G_ubf_db->dbi_id, &key, &data, 0)))
0380     {
0381         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0382                 "%s: Failed to put ID (id=%d/[%s]) record: %s", 
0383                 __func__, (int)idcomp, entry.fldname, edb_strerror(ret));   
0384         EXFAIL_OUT(ret);
0385     }
0386     
0387     UBF_LOG(log_debug, "About to put NAME record (%d) / [%s]", (int)idcomp, 
0388             entry.fldname);
0389     
0390     key.mv_data = entry.fldname;
0391     key.mv_size = strlen(entry.fldname)+1;
0392     
0393     if (EXSUCCEED!=(ret=edb_put(txn, ndrx_G_ubf_db->dbi_nm, &key, &data, 0)))
0394     {
0395         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0396                 "%s: Failed to put ID (id=%d/[%s]) record: %s", 
0397                 __func__, (int)idcomp, entry.fldname, edb_strerror(ret));   
0398         EXFAIL_OUT(ret);
0399     }
0400     
0401 out:    
0402 
0403     UBF_LOG(log_debug, "%s returns %d", __func__, ret);
0404 
0405     return ret;
0406 }
0407 
0408 /**
0409  * Delete field by id (deletes from both NM & ID bases)
0410  * @param txn LMDB transaction into which delete the field
0411  * @param bfldid compiled field id
0412  * @return EXSUCCEED/EXFAIL (Berror set)
0413  */
0414 expublic int ndrx_ubfdb_Bflddbdel(EDB_txn *txn, BFLDID bfldid)
0415 {
0416     int ret = EXSUCCEED;
0417     char fldname[UBFFLDMAX+1] = {EXEOS};
0418     char *p;
0419     EDB_val key;
0420     
0421     key.mv_data = &bfldid;
0422     key.mv_size = sizeof(bfldid);
0423     
0424     if (NULL==(p = Bfname(bfldid)))
0425     {
0426         NDRX_UBFDB_BERRORNOU(log_info, BNOTPRES, "Field by id: %d not found!",
0427                     (int)bfldid);
0428         EXFAIL_OUT(ret);
0429     }
0430     
0431     NDRX_STRCPY_SAFE(fldname, p);
0432     /* Delete ID: */
0433     UBF_LOG(log_debug, "%s: delete by %d", __func__, (int)bfldid);
0434     
0435     if (EXSUCCEED!=(ret=edb_del(txn, ndrx_G_ubf_db->dbi_id, &key, NULL)))
0436     {
0437         if (ret!=EDB_NOTFOUND)
0438         {
0439             NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0440                     "%s: Failed to delete by ID (id=%d) record: %s", 
0441                     __func__, (int)bfldid, edb_strerror(ret));   
0442             EXFAIL_OUT(ret);
0443         }
0444         else
0445         {
0446             UBF_LOG(log_info, "%s: Field [%d] not found in db", __func__, 
0447                     (int)bfldid);
0448         }
0449     }
0450     
0451     UBF_LOG(log_debug, "About to delete by NAME [%s]", fldname);
0452     
0453     key.mv_data = fldname;
0454     key.mv_size = strlen(fldname)+1;
0455     
0456     if (EXSUCCEED!=(ret=edb_del(txn, ndrx_G_ubf_db->dbi_nm, &key, NULL)))
0457     {
0458         if (ret!=EDB_NOTFOUND)
0459         {
0460             NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0461                     "%s: Failed to delete by field name ([%s]) record: %s", 
0462                     __func__, fldname, edb_strerror(ret));   
0463             EXFAIL_OUT(ret);
0464         }
0465         else
0466         {
0467             UBF_LOG(log_info, "%s: Field [%s] not found in db", 
0468                     __func__, fldname);
0469             ret=EXSUCCEED;
0470         }
0471     }
0472     
0473 out:    
0474 
0475     UBF_LOG(log_debug, "%s returns %d", __func__, ret);
0476 
0477     return ret;
0478 }
0479 
0480 /**
0481  * Delete all records form db (ID & NM)
0482  * @param txn LMDB transaction into which delete the fields
0483  * @return EXSUCCEED/EXFAIL (B error set)
0484  */
0485 expublic int ndrx_ubfdb_Bflddbdrop(EDB_txn *txn)
0486 {
0487     int ret = EXSUCCEED;
0488     
0489     if (EXSUCCEED!=(ret=edb_drop(txn, ndrx_G_ubf_db->dbi_id, 0)))
0490     {
0491         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0492                 "%s: Failed to drop id db: %s", 
0493                 __func__, edb_strerror(ret));   
0494         EXFAIL_OUT(ret);
0495     }
0496     
0497     if (EXSUCCEED!=(ret=edb_drop(txn, ndrx_G_ubf_db->dbi_nm, 0)))
0498     {
0499         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0500                 "%s: Failed to drop name db: %s", 
0501                 __func__, edb_strerror(ret));   
0502         EXFAIL_OUT(ret);
0503     }
0504     
0505 out:
0506     return ret;
0507 }
0508 
0509 /**
0510  * Close the database
0511  * @return 
0512  */
0513 expublic void ndrx_ubfdb_Bflddbunload(void)
0514 {
0515     ndrx_G_ubf_db_triedload=EXFALSE;
0516     
0517     if (NULL!=ndrx_G_ubf_db)
0518     {
0519         edb_dbi_close(ndrx_G_ubf_db->env, ndrx_G_ubf_db->dbi_id);
0520         edb_dbi_close(ndrx_G_ubf_db->env, ndrx_G_ubf_db->dbi_nm);
0521         edb_env_close(ndrx_G_ubf_db->env);
0522         
0523         NDRX_FREE(ndrx_G_ubf_db);
0524         
0525         ndrx_G_ubf_db = NULL;
0526     } 
0527 }
0528 
0529 /**
0530  * Unlink the field database (delete data files)
0531  * @return EXSUCCEED/EXFAIL (UBF error set)
0532  */
0533 expublic int ndrx_ubfdb_Bflddbunlink(void)
0534 {
0535     int ret = EXSUCCEED;
0536     char errdet[MAX_TP_ERROR_LEN+1];
0537     ndrx_inicfg_section_keyval_t * csection = NULL, *res = NULL;
0538     
0539     if (EXSUCCEED!=ndrx_cconfig_get(NDRX_CONF_SECTION_UBFDB, &csection))
0540     {
0541         UBF_LOG(log_debug, "UBF DB not defined");
0542         goto out;
0543     }
0544     
0545     EXHASH_FIND_STR( csection, NDRX_UBFDB_KWD_RESOURCE, res);
0546     
0547     if (NULL!=res)
0548     {
0549         if (EXSUCCEED!=ndrx_mdb_unlink(res->val, errdet, sizeof(errdet), 
0550                 LOG_CODE_UBF))
0551         {
0552             NDRX_UBFDB_BERROR(BEUNIX, 
0553                     "%s: Failed to unlink [%s] UBF DB: %s", 
0554                     __func__, res->val, errdet);
0555             EXFAIL_OUT(ret);
0556         }
0557     }
0558     else
0559     {
0560         UBF_LOG(log_debug, "%s: no UBF DB [%s] section found in config", 
0561                 __func__, NDRX_CONF_SECTION_UBFDB);
0562     }
0563     
0564 out:
0565 
0566     if (NULL!=csection)
0567         ndrx_keyval_hash_free(csection);
0568 
0569     return ret;
0570 }
0571 
0572 /**
0573  * Extract data from UBF DB record
0574  * @param val value returned by cursor
0575  * @param p_fldtype field type id
0576  * @param p_bfldno field number
0577  * @param p_bfldid field id
0578  * @param fldname field name
0579  * @param fldname_bufsz filed name buffer size
0580  * @return EXSUCCEED/EXFAIL (Berror set)
0581  */
0582 expublic int ndrx_ubfdb_Bflddbget(EDB_val *data,
0583         short *p_fldtype, BFLDID *p_bfldno, BFLDID *p_bfldid, 
0584         char *fldname, int fldname_bufsz)
0585 {
0586     int ret = EXSUCCEED;
0587     ndrx_ubfdb_entry_t *entry;
0588     
0589     if (data->mv_size!=sizeof(ndrx_ubfdb_entry_t))
0590     {
0591         NDRX_UBFDB_BERROR(BEINVAL, 
0592                     "%s: Expected data size %d, but got %d!", 
0593                     __func__, (int)sizeof(ndrx_ubfdb_entry_t), (int)data->mv_size);
0594             EXFAIL_OUT(ret);
0595     }
0596     
0597     entry = (ndrx_ubfdb_entry_t *)data->mv_data;
0598     
0599 #ifdef EX_ALIGNMENT_FORCE
0600     memcpy(p_bfldid, &(entry->bfldid), sizeof(BFLDID));
0601 #else
0602     *p_bfldid = entry->bfldid;
0603 #endif
0604 
0605     *p_bfldno = (*p_bfldid) & EFFECTIVE_BITS_MASK;
0606     *p_fldtype = (*p_bfldid) >> EFFECTIVE_BITS;
0607     
0608     NDRX_STRCPY_SAFE_DST(fldname, entry->fldname, fldname_bufsz);
0609     
0610     UBF_LOG(log_debug, "%s: fldno=%d fldid=%d fldtype=%d fldname=[%s]",
0611                 __func__, *p_bfldno, *p_bfldid, *p_fldtype, fldname);
0612 out:   
0613     return ret;
0614 }
0615 
0616 /**
0617  * Resolve field id from field name
0618  * Lookup transaction is generated locally.
0619  * @param fldnm
0620  * @return ptr to field (TLS) or NULL (B error set)
0621  */
0622 expublic char * ndrx_ubfdb_Bflddbname (BFLDID bfldid)
0623 {
0624     int ret = EXSUCCEED;
0625     EDB_txn *txn = NULL;
0626     int tran_started = EXFALSE;
0627     EDB_val key, data;
0628     static __thread char fname[UBFFLDMAX+1];
0629     ndrx_ubfdb_entry_t *entry;
0630     
0631     if (NULL==ndrx_G_ubf_db)
0632     {
0633         NDRX_UBFDB_BERRORNOU(log_error, BBADFLD, 
0634                 "%s: no CC config defined for UBF DB", __func__);
0635         return NULL;
0636     }
0637     
0638     /* Prepare the DB */
0639     if (EXSUCCEED!=(ret=edb_txn_begin(ndrx_G_ubf_db->env, NULL, EDB_RDONLY, &txn)))
0640     {
0641         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0642                 "%s: Failed to begin transaction for ubf db: %s", 
0643                 __func__, edb_strerror(ret));
0644         
0645         EXFAIL_OUT(ret);
0646     }
0647 
0648     tran_started = EXTRUE;
0649     
0650     key.mv_size = sizeof(bfldid);
0651     key.mv_data = &bfldid;
0652     
0653     if (EXSUCCEED!=(ret=edb_get(txn, ndrx_G_ubf_db->dbi_id, &key, &data)))
0654     {
0655         if (ret==EDB_NOTFOUND)
0656         {
0657             /* ok, this is weak error */
0658             NDRX_UBFDB_BERRORNOU(log_info, ndrx_ubfdb_maperr(ret), 
0659                     "%s: Field not present in UBF DB (%d): %s", 
0660                     __func__, (int)bfldid, edb_strerror(ret));
0661             EXFAIL_OUT(ret);
0662         }
0663         else
0664         {
0665             NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0666                     "%s: Failed to get data by field id %d: %s", 
0667                     __func__, (int)bfldid, edb_strerror(ret));
0668         }
0669         EXFAIL_OUT(ret);
0670     }
0671     
0672     if (sizeof(*entry)!=data.mv_size)
0673     {
0674         NDRX_UBFDB_BERROR(BEINVAL, 
0675                 "%s: Invalid data size expected %d got %d", 
0676                 __func__, (int)sizeof(*entry), (int)data.mv_size);
0677         
0678         EXFAIL_OUT(ret);
0679     }
0680     
0681     entry = (ndrx_ubfdb_entry_t *)data.mv_data;
0682     
0683     NDRX_STRCPY_SAFE(fname, entry->fldname);
0684     
0685     
0686     UBF_LOG(log_debug, "%s: bfldid=%d resolved to [%s]", __func__, bfldid, 
0687             fname);
0688     
0689 out:
0690     
0691     /* for reads we can abort easily */
0692     if (tran_started)
0693     {
0694         edb_txn_abort(txn);
0695     }
0696 
0697     if (EXSUCCEED==ret)
0698     {
0699         return fname;
0700     }
0701 
0702     return NULL;
0703 }
0704 
0705 /**
0706  * Resolve field by name
0707  * @param fldname filed name
0708  * @return Field id or BBADFLDID (B error set)
0709  */
0710 expublic BFLDID ndrx_ubfdb_Bflddbid (char *fldname)
0711 {
0712     int ret = EXSUCCEED;
0713     EDB_txn *txn = NULL;
0714     int tran_started = EXFALSE;
0715     EDB_val key, data;
0716     ndrx_ubfdb_entry_t *entry;
0717     
0718     if (NULL==ndrx_G_ubf_db)
0719     {
0720         NDRX_UBFDB_BERRORNOU(log_error, BBADNAME, 
0721                 "%s: no CC config defined for UBF DB", __func__);
0722         return BBADFLDID;
0723     }
0724     
0725     /* Prepare the DB */
0726     if (EXSUCCEED!=(ret=edb_txn_begin(ndrx_G_ubf_db->env, NULL, EDB_RDONLY, &txn)))
0727     {
0728         NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0729                 "%s: Failed to begin transaction for ubf db: %s", 
0730                 __func__, edb_strerror(ret));
0731         
0732         EXFAIL_OUT(ret);
0733     }
0734 
0735     tran_started = EXTRUE;
0736     
0737     key.mv_size = strlen(fldname)+1;
0738     key.mv_data = fldname;
0739     
0740     if (EXSUCCEED!=(ret=edb_get(txn, ndrx_G_ubf_db->dbi_nm, &key, &data)))
0741     {
0742         if (ret==EDB_NOTFOUND)
0743         {
0744             /* ok, this is weak error */
0745             NDRX_UBFDB_BERRORNOU(log_info, BBADNAME, 
0746                     "%s: Field not present in UBF DB by name [%s]: %s", 
0747                     __func__, fldname, edb_strerror(ret));
0748             EXFAIL_OUT(ret);
0749         }
0750         else
0751         {
0752             NDRX_UBFDB_BERROR(ndrx_ubfdb_maperr(ret), 
0753                     "%s: Failed to get data by field name [%s]: %s", 
0754                     __func__, fldname, edb_strerror(ret));
0755         }
0756         EXFAIL_OUT(ret);
0757     }
0758     
0759     if (sizeof(*entry)!=data.mv_size)
0760     {
0761         NDRX_UBFDB_BERROR(BEINVAL, 
0762                 "%s: Invalid data size expected %d got %d", 
0763                 __func__, (int)sizeof(*entry), (int)data.mv_size);
0764         
0765         EXFAIL_OUT(ret);
0766     }
0767     
0768     entry = (ndrx_ubfdb_entry_t *)data.mv_data;
0769     
0770 #ifdef EX_ALIGNMENT_FORCE
0771     /* for sparc aligned access we might want to use memcpy... */
0772     memcpy(&ret, &(entry->bfldid), sizeof(ret));
0773 #else
0774     ret = entry->bfldid;
0775 #endif
0776     
0777     UBF_LOG(log_debug, "%s: name [%s] resolved to field id %d", __func__, 
0778             fldname, ret);
0779     
0780 out:
0781     
0782     /* for reads we can abort easily */
0783     if (tran_started)
0784     {
0785         edb_txn_abort(txn);
0786     }
0787 
0788     if (ret<0)
0789     {
0790         return BBADFLDID;
0791     }
0792 
0793     return ret;
0794 }
0795 
0796 /**
0797  * Get the LMDB database environment handle
0798  * @param[out] dbi_id id database handler
0799  * @param[out] dbi_nm name database handler
0800  * @return NULL if no env set, or env ptr
0801  */
0802 expublic EDB_env * ndrx_ubfdb_Bfldddbgetenv (EDB_dbi **dbi_id, EDB_dbi **dbi_nm)
0803 {
0804     EDB_env * ret = NULL;
0805     
0806     if (NULL!=ndrx_G_ubf_db)
0807     {
0808         *dbi_id = &ndrx_G_ubf_db->dbi_id;
0809         *dbi_nm = &ndrx_G_ubf_db->dbi_nm;
0810         ret = ndrx_G_ubf_db->env;
0811     }
0812     
0813 out:
0814     return ret;
0815 }
0816 
0817 /* vim: set ts=4 sw=4 et smartindent: */