Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Globals/TLS for libnstd
0003  *   All stuff here must work. thus if something is very bad, we ill print to stderr.
0004  *
0005  * @file nstd_tls.c
0006  */
0007 /* -----------------------------------------------------------------------------
0008  * Enduro/X Middleware Platform for Distributed Transaction Processing
0009  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0010  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0011  * This software is released under one of the following licenses:
0012  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0013  * See LICENSE file for full text.
0014  * -----------------------------------------------------------------------------
0015  * AGPL license:
0016  *
0017  * This program is free software; you can redistribute it and/or modify it under
0018  * the terms of the GNU Affero General Public License, version 3 as published
0019  * by the Free Software Foundation;
0020  *
0021  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0022  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0023  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0024  * for more details.
0025  *
0026  * You should have received a copy of the GNU Affero General Public License along 
0027  * with this program; if not, write to the Free Software Foundation, Inc.,
0028  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0029  *
0030  * -----------------------------------------------------------------------------
0031  * A commercial use license is available from Mavimax, Ltd
0032  * contact@mavimax.com
0033  * -----------------------------------------------------------------------------
0034  */
0035 
0036 /*---------------------------Includes-----------------------------------*/
0037 #include <stdlib.h>
0038 #include <stdio.h>
0039 #include <ndrstandard.h>
0040 #include <nstdutil.h>
0041 #include <nstd_tls.h>
0042 #include <string.h>
0043 #include "thlock.h"
0044 #include "userlog.h"
0045 #include "ndebug.h"
0046 /*---------------------------Externs------------------------------------*/
0047 /*---------------------------Macros-------------------------------------*/
0048 /*---------------------------Enums--------------------------------------*/
0049 /*---------------------------Typedefs-----------------------------------*/
0050 /*---------------------------Globals------------------------------------*/
0051 __thread nstd_tls_t *G_nstd_tls = NULL; /* single place for library TLS storage */
0052 /*---------------------------Statics------------------------------------*/
0053 exprivate pthread_key_t M_nstd_tls_key;
0054 exprivate MUTEX_LOCKDECL(M_thdata_init);
0055 exprivate int M_first = EXTRUE;
0056 /*---------------------------Prototypes---------------------------------*/
0057 
0058 /**
0059  * Unlock, unset G_nstd_tls, return pointer to G_nstd_tls
0060  * @return 
0061  */
0062 expublic void * ndrx_nstd_tls_get(void)
0063 {
0064     nstd_tls_t *tmp = G_nstd_tls;
0065     
0066     G_nstd_tls = NULL;
0067     
0068     if (NULL!=tmp)
0069     {
0070         /*
0071          * Unset the destructor
0072          */
0073         if (tmp->is_auto)
0074         {
0075             pthread_setspecific( M_nstd_tls_key, NULL );
0076         }
0077 
0078         /* unlock object */
0079         MUTEX_UNLOCK_V(tmp->mutex);
0080     }
0081     
0082     return (void *)tmp;
0083 }
0084 
0085 /**
0086  * Get the lock & set the G_nstd_tls to this one
0087  * @param tls
0088  */
0089 expublic int ndrx_nstd_tls_set(void *data)
0090 {
0091     nstd_tls_t *tls = (nstd_tls_t *)data;
0092     
0093     if (NULL!=tls)
0094     {
0095         /* extra control... */
0096         if (NSTD_TLS_MAGIG!=tls->magic)
0097         {
0098             userlog("nstd_tls_set: invalid magic! expected: %x got %x", 
0099                     NSTD_TLS_MAGIG, tls->magic);
0100         }
0101 
0102         /* Lock the object */
0103         MUTEX_LOCK_V(tls->mutex);
0104 
0105         G_nstd_tls = tls;
0106 
0107         /*
0108          * Destruct automatically if it was auto-tls 
0109          */
0110         if (tls->is_auto)
0111         {
0112             pthread_setspecific( M_nstd_tls_key, (void *)tls );
0113         }
0114     }
0115     else
0116     {
0117         G_nstd_tls = NULL;
0118     }
0119 
0120     return EXSUCCEED;
0121 }
0122 
0123 /**
0124  * Free up the TLS data
0125  * @param tls
0126  * @return 
0127  */
0128 expublic void ndrx_nstd_tls_free(void *data)
0129 {
0130     if (NULL!=data)
0131     {
0132         if (data==G_nstd_tls)
0133         {
0134             if (G_nstd_tls->is_auto)
0135             {
0136                 pthread_setspecific( M_nstd_tls_key, NULL );
0137             }
0138             G_nstd_tls=NULL;
0139         }
0140         
0141         /* Close debug loggers? Bug #274 */
0142         ndrx_nstd_tls_loggers_close((nstd_tls_t *)data);
0143         
0144         NDRX_FREE((char*)data);
0145     }
0146 }
0147 
0148 /**
0149  * Get the lock & init the data
0150  * @param auto_destroy if set to 1 then when tried exits, thread data will be made free
0151  * @return 
0152  */
0153 expublic void * ndrx_nstd_tls_new(int auto_destroy, int auto_set)
0154 {
0155     int ret = EXSUCCEED;
0156     nstd_tls_t *tls  = NULL;
0157     char fn[] = "nstd_context_new";
0158     
0159     /* init they key storage */
0160     
0161     if (M_first)
0162     {
0163         MUTEX_LOCK_V(M_thdata_init);
0164         if (M_first)
0165         {
0166             pthread_key_create( &M_nstd_tls_key, 
0167                     &ndrx_nstd_tls_free );
0168             M_first = EXFALSE;
0169         }
0170         MUTEX_UNLOCK_V(M_thdata_init);
0171     }
0172     
0173     if (NULL==(tls = (nstd_tls_t *)NDRX_MALLOC(sizeof(nstd_tls_t))))
0174     {
0175         userlog ("%s: failed to malloc", fn);
0176         EXFAIL_OUT(ret);
0177     }
0178     
0179     /* do the common init... */
0180     tls->magic = NSTD_TLS_MAGIG;
0181     tls->M_threadnr = 0;
0182     tls->M_nstd_error = 0;
0183     tls->M_last_err = 0;
0184     tls->M_last_err_msg[0] = EXEOS;
0185     tls->rand_init = EXFALSE;
0186     
0187     /* disable log handlers: */
0188     memset(&tls->threadlog_tp, 0, sizeof(tls->threadlog_tp));
0189     memset(&tls->requestlog_tp, 0, sizeof(tls->requestlog_tp));
0190     
0191     memset(&tls->threadlog_ndrx, 0, sizeof(tls->threadlog_ndrx));
0192     memset(&tls->requestlog_ndrx, 0, sizeof(tls->requestlog_ndrx));
0193     
0194     memset(&tls->threadlog_ubf, 0, sizeof(tls->threadlog_ubf));
0195     memset(&tls->requestlog_ubf, 0, sizeof(tls->requestlog_ubf));
0196     
0197     tls->threadlog_tp.level = EXFAIL;
0198     tls->requestlog_tp.level = EXFAIL;
0199     tls->threadlog_ndrx.level = EXFAIL;
0200     tls->requestlog_ndrx.level = EXFAIL;
0201     tls->threadlog_ubf.level = EXFAIL;
0202     tls->requestlog_ubf.level = EXFAIL;
0203     
0204     tls->threadlog_tp.flags = LOG_FACILITY_TP_THREAD;
0205     tls->requestlog_tp.flags = LOG_FACILITY_TP_REQUEST;
0206     tls->threadlog_ndrx.flags = LOG_FACILITY_NDRX_THREAD;
0207     tls->requestlog_ndrx.flags = LOG_FACILITY_NDRX_REQUEST;
0208     tls->threadlog_ubf.flags = LOG_FACILITY_UBF_THREAD;
0209     tls->requestlog_ubf.flags = LOG_FACILITY_UBF_REQUEST;
0210     
0211     tls->threadlog_tp.code = LOG_CODE_TP_THREAD;
0212     tls->requestlog_tp.code = LOG_CODE_TP_REQUEST;
0213     tls->threadlog_ndrx.code = LOG_CODE_NDRX_THREAD;
0214     tls->requestlog_ndrx.code = LOG_CODE_NDRX_REQUEST;
0215     tls->threadlog_ubf.code = LOG_CODE_UBF_THREAD;
0216     tls->requestlog_ubf.code = LOG_CODE_UBF_REQUEST;
0217     
0218     NDRX_STRCPY_SAFE(tls->threadlog_ubf.module, "UBF ");
0219     NDRX_STRCPY_SAFE(tls->threadlog_ndrx.module, "NDRX");
0220     NDRX_STRCPY_SAFE(tls->threadlog_tp.module, "USER");
0221    
0222     NDRX_STRCPY_SAFE(tls->requestlog_ubf.module, "UBF ");
0223     NDRX_STRCPY_SAFE(tls->requestlog_ndrx.module, "NDRX");
0224     NDRX_STRCPY_SAFE(tls->requestlog_tp.module, "USER");
0225         
0226     tls->user_field_1 = 0;
0227     
0228     pthread_mutex_init(&tls->mutex, NULL);
0229     
0230     /* set callback, when thread dies, we need to get the destructor 
0231      * to be called
0232      */
0233     if (auto_destroy)
0234     {
0235         tls->is_auto = EXTRUE;
0236         pthread_setspecific( M_nstd_tls_key, (void *)tls );
0237     }
0238     else
0239     {
0240         tls->is_auto = EXFALSE;
0241     }
0242     
0243     if (auto_set)
0244     {
0245         ndrx_nstd_tls_set(tls);
0246     }
0247     
0248 out:
0249 
0250     if (EXSUCCEED!=ret && NULL!=tls)
0251     {
0252         ndrx_nstd_tls_free((char *)tls);
0253     }
0254 
0255     return (void *)tls;
0256 }
0257 
0258 /* vim: set ts=4 sw=4 et smartindent: */