Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Process messages from linked list (deletes to avoid RW cursors)
0003  *
0004  * @file msglist.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 #include <string.h>
0035 #include <stdio.h>
0036 #include <stdlib.h>
0037 #include <memory.h>
0038 
0039 #include <atmi.h>
0040 #include <atmi_int.h>
0041 #include <atmi_shm.h>
0042 #include <ndrstandard.h>
0043 #include <Exfields.h>
0044 #include <ubf.h>
0045 #include <ubf_int.h>
0046 #include <ndebug.h>
0047 #include <atmi_cache.h>
0048 #include "tpcached.h"
0049 #include "utlist.h"
0050 /*---------------------------Externs------------------------------------*/
0051 /*---------------------------Macros-------------------------------------*/    
0052 /*---------------------------Enums--------------------------------------*/
0053 /*---------------------------Typedefs-----------------------------------*/
0054 /*---------------------------Globals------------------------------------*/
0055 /*---------------------------Statics------------------------------------*/
0056 /*---------------------------Prototypes---------------------------------*/
0057 
0058 
0059 /**
0060  * Free up record
0061  * @param entry linked list record
0062  */
0063 exprivate void free_rec(ndrx_tpcached_msglist_t * entry)
0064 {
0065     if (NULL!=entry->keydb.mv_data)
0066     {
0067         NDRX_FREE(entry->keydb.mv_data);
0068     }
0069     
0070     if (NULL!=entry->val.mv_data)
0071     {
0072         NDRX_FREE(entry->val.mv_data);
0073     }
0074     
0075     NDRX_FREE(entry);
0076 }
0077 
0078 /**
0079  * Add message to linked list
0080  * @param list list to be created or msg added
0081  * @param keydb key db (mandatory)
0082  * @param val value optional (may be NULL)
0083  * @return EXSUCCEED/EXFAIL
0084  */
0085 expublic int ndrx_tpcached_add_msg(ndrx_tpcached_msglist_t ** list,
0086         EDB_val *keydb, EDB_val *val)
0087 {
0088     int ret = EXSUCCEED;
0089     ndrx_tpcached_msglist_t * entry = NULL;
0090     
0091     
0092     /* Allocate MSG list entry */
0093     
0094     NDRX_CALLOC_OUT(entry, 1, sizeof(ndrx_tpcached_msglist_t), ndrx_tpcached_msglist_t);
0095     
0096     /* fill up the key */
0097     entry->keydb.mv_size = keydb->mv_size;
0098     NDRX_MALLOC_OUT(entry->keydb.mv_data, entry->keydb.mv_size, void);
0099     memcpy(entry->keydb.mv_data, keydb->mv_data, entry->keydb.mv_size);
0100     
0101     /* fill up the data, if provided */
0102     
0103     if (NULL!=val)
0104     {
0105         entry->val.mv_size = val->mv_size;
0106         NDRX_MALLOC_OUT(entry->val.mv_data, entry->val.mv_size, void);
0107         memcpy(entry->val.mv_data, val->mv_data, entry->val.mv_size);
0108         
0109         entry->is_full = EXTRUE;
0110     }
0111     
0112     LL_APPEND((*list), entry);
0113     entry = NULL;
0114     
0115 out:
0116     if (NULL!=entry)
0117     {
0118         free_rec(entry);
0119     }
0120     return ret;
0121 }
0122 
0123 /**
0124  * Remove all messages from linked list, we run RW transaction!!! (ALL LOCKS)!
0125  * @param list list of msg to delete
0126  * @return EXSUCCEED/EXFAIL
0127  */
0128 expublic int ndrx_tpcached_kill_list(ndrx_tpcache_db_t *db, 
0129         ndrx_tpcached_msglist_t ** list)
0130 {
0131     int ret = EXSUCCEED;
0132     ndrx_tpcached_msglist_t * el, *elt;
0133     EDB_txn *txn = NULL;
0134     int tran_started = EXFALSE;
0135     int deleted = 0;
0136     short nodeid = (short)tpgetnodeid();
0137     /* start new rw transaction  */
0138     
0139     if (EXSUCCEED!=ndrx_cache_edb_begin(db, &txn, 0))
0140     {
0141         NDRX_LOG(log_error, "Failed start transaction: %s", 
0142                 tpstrerror(tperrno));
0143         EXFAIL_OUT(ret);
0144     }
0145     tran_started = EXTRUE;
0146     
0147     LL_FOREACH_SAFE((*list), el, elt)
0148     {
0149         if (el->is_full)
0150         {
0151             NDRX_LOG(log_debug, "Delete by key + data (key: [%s])", el->keydb.mv_data);
0152             
0153             if (EXSUCCEED!=(ret=ndrx_cache_edb_del (db, txn, el->keydb.mv_data, 
0154                     &el->val)))
0155             {
0156                 if (ret!=EDB_NOTFOUND)
0157                 {
0158                     EXFAIL_OUT(ret);
0159                 }
0160                 else
0161                 {
0162                     ret=EXSUCCEED;
0163                 }
0164             }
0165             
0166         }
0167         else
0168         {
0169             NDRX_LOG(log_debug, "Delete by key only with bcast(key: [%s])", 
0170                     el->keydb.mv_data);
0171             
0172             if (EXSUCCEED!=ndrx_cache_inval_by_key(db->cachedb, db, 
0173                     el->keydb.mv_data, nodeid, txn, EXTRUE))
0174             {
0175                 NDRX_LOG(log_debug, "Failed to delete record by key [%s]", 
0176                         el->keydb.mv_data);
0177                 EXFAIL_OUT(ret);
0178             }
0179         }
0180         
0181         LL_DELETE(*list, el);
0182         free_rec(el);
0183         deleted++;
0184     }
0185     
0186 out:
0187     
0188     if (tran_started)
0189     {
0190         if (EXSUCCEED==ret)
0191         {
0192             if (EXSUCCEED!=ndrx_cache_edb_commit(db, txn))
0193             {
0194                 NDRX_CACHE_TPERROR(TPESYSTEM, "%s: Failed to commit: %s", 
0195                     __func__, tpstrerror(tperrno));
0196                 ndrx_cache_edb_abort(db, txn);
0197             }
0198         }
0199         else
0200         {
0201             ndrx_cache_edb_abort(db, txn);
0202         }
0203     }
0204 
0205     if (EXSUCCEED==ret)
0206     {
0207         NDRX_LOG(log_info, "%s: delete %d rec(s)", __func__, deleted);
0208         return deleted;
0209     }
0210     else
0211     {
0212         NDRX_LOG(log_info, "%s: returns %d", __func__, ret);
0213         return ret;
0214     }
0215 }
0216 
0217 /**
0218  * Just clean up the list
0219  * @param list
0220  */
0221 expublic void ndrx_tpcached_free_list(ndrx_tpcached_msglist_t ** list)
0222 {
0223     ndrx_tpcached_msglist_t * el, *elt;
0224     LL_FOREACH_SAFE((*list), el, elt)
0225     {
0226         LL_DELETE(*list, el);
0227         free_rec(el);;
0228     }
0229 }
0230 /* vim: set ts=4 sw=4 et smartindent: */