Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief TP LOG, full feature logging system for user, mainly for exporting to
0003  *   to other languages. C/C++ can use ndebug.h
0004  *   TODO: tplog* func shall have pull in of init in case if they are called first
0005  *
0006  * @file tplog.c
0007  */
0008 /* -----------------------------------------------------------------------------
0009  * Enduro/X Middleware Platform for Distributed Transaction Processing
0010  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0011  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0012  * This software is released under one of the following licenses:
0013  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0014  * See LICENSE file for full text.
0015  * -----------------------------------------------------------------------------
0016  * AGPL license:
0017  *
0018  * This program is free software; you can redistribute it and/or modify it under
0019  * the terms of the GNU Affero General Public License, version 3 as published
0020  * by the Free Software Foundation;
0021  *
0022  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0023  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0024  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0025  * for more details.
0026  *
0027  * You should have received a copy of the GNU Affero General Public License along 
0028  * with this program; if not, write to the Free Software Foundation, Inc.,
0029  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0030  *
0031  * -----------------------------------------------------------------------------
0032  * A commercial use license is available from Mavimax, Ltd
0033  * contact@mavimax.com
0034  * -----------------------------------------------------------------------------
0035  */
0036 #include <ndrx_config.h>
0037 #include <string.h>
0038 #include <stdio.h>
0039 #include <stdlib.h>
0040 #include <memory.h>
0041 #include <time.h>
0042 #include <sys/time.h>
0043 #include <unistd.h>
0044 #include <stdarg.h>
0045 
0046 #include <ndrstandard.h>
0047 #include <ndebug.h>
0048 #include <nstdutil.h>
0049 #include <sys_unix.h>
0050 #include <userlog.h>
0051 #include <nstd_tls.h>
0052 #include <errno.h>
0053 #include <nstd_int.h>
0054 
0055 #include "atmi_tls.h"
0056 /*---------------------------Externs------------------------------------*/
0057 /*---------------------------Macros-------------------------------------*/
0058 #define API_ENTRY {_Nunset_error();}
0059 
0060 /**
0061  * Get logger mapping,
0062  * used in source code to perform inits
0063  */
0064 #define LOGGER_MAP { \
0065         {&G_nstd_tls->requestlog_tp, &G_nstd_tls->threadlog_tp, &G_tp_debug} \
0066         ,{&G_nstd_tls->requestlog_ndrx, &G_nstd_tls->threadlog_ndrx, &G_ndrx_debug} \
0067         ,{&G_nstd_tls->requestlog_ubf, &G_nstd_tls->threadlog_ubf, &G_ubf_debug} \
0068     }
0069 
0070 
0071 /**
0072  * Define save fields for module init
0073  */
0074 #define LOGGER_SAVE_FIELDS_DEF \
0075     char sav_code; \
0076     long sav_flags; \
0077     char sav_module[NDRX_LOG_MODULE_LEN+1];
0078     
0079 /**
0080  * Do save op
0081  */
0082 #define LOGGER_SAVE_FIELDS(LOGGERPTR) \
0083     sav_code = LOGGERPTR->code; \
0084     sav_flags = LOGGERPTR->flags; \
0085     NDRX_STRCPY_SAFE(sav_module, LOGGERPTR->module);
0086     
0087 /**
0088  * Do field restore op
0089  */
0090 #define LOGGER_RESTORE_FIELDS(LOGGERPTR) \
0091     LOGGERPTR->code = sav_code; \
0092     LOGGERPTR->flags = sav_flags; \
0093     NDRX_STRCPY_SAFE(LOGGERPTR->module, sav_module);
0094     
0095 /*---------------------------Enums--------------------------------------*/
0096 /*---------------------------Typedefs-----------------------------------*/
0097 
0098 /**
0099  * Debug mapping for req log open/close
0100  */
0101 typedef struct
0102 {
0103     ndrx_debug_t *req;  /**< request logging settings               */
0104     ndrx_debug_t *th;   /**< thread logging settings                */
0105     ndrx_debug_t *proc; /**< base logging settings (non TLS)        */
0106 } debug_map_t;
0107 
0108 /*---------------------------Globals------------------------------------*/
0109 /*---------------------------Statics------------------------------------*/
0110 exprivate MUTEX_LOCKDECL(M_proc_lock); /**< lock process level loggers */
0111 /*---------------------------Prototypes---------------------------------*/
0112 exprivate ndrx_debug_t * ndrx_tplog_getlogger(int logger);
0113 
0114 /**
0115  * Close any TLS loggers if open
0116  * @param tls thread local storage for ATMI lib
0117  */
0118 expublic void ndrx_nstd_tls_loggers_close(nstd_tls_t *tls)
0119 {
0120     ndrx_debug_t *nlogger[] = {&tls->threadlog_ndrx, &tls->threadlog_ubf, 
0121         &tls->threadlog_tp, &tls->requestlog_ndrx, &tls->requestlog_ubf, 
0122         &tls->requestlog_tp, NULL};
0123     int i=0;
0124     
0125     while (NULL!=nlogger[i])
0126     {
0127         if (NULL!=nlogger[i]->dbg_f_ptr)
0128         {
0129             ndrx_debug_unset_sink(nlogger[i]->dbg_f_ptr, EXTRUE, EXFALSE);
0130             nlogger[i]->dbg_f_ptr=NULL;
0131             /* clear the file names */
0132             nlogger[i]->filename[0]=EXEOS;
0133             nlogger[i]->level = EXFAIL;
0134         }
0135         i++;
0136     }
0137     
0138 }
0139 
0140 /**
0141  * Setup the request logging file.  
0142  * NOTE that we need: 
0143  * 1. tplogsetreqfile(<buffer>, <filename> (optional, not needed if name already in buffer))
0144  * 2. tploggetreqfile(fname (out)) return TRUE/FALSE if we have, and string with the value of fname
0145  * 3. tplogclosereqfile(); close thre request logging.
0146  * File will be set to EX_REQLOG = <Full path to request log file>
0147  * Feature #470 This now applies TP/NDRX/UBF facilities.
0148  * @param filename file name to log to
0149  */
0150 expublic void tplogsetreqfile_direct(const char *filename)
0151 {
0152     debug_map_t map[] = LOGGER_MAP;
0153     int i, dosetup=EXFALSE;
0154         
0155     API_ENTRY; /* set TLS too */
0156     /* have a scope: */
0157     do 
0158     {
0159         
0160         LOGGER_SAVE_FIELDS_DEF;
0161 
0162         for (i=0; i<N_DIM(map); i++)
0163         {
0164             /* Level not set, then there was no init */
0165             if (EXFAIL==map[i].req->level)
0166             {   
0167                 LOGGER_SAVE_FIELDS(map[i].req);
0168 
0169                 /* file is null, we want to copy off the settings  */
0170                 if (NULL!=map[i].th->dbg_f_ptr)
0171                 {
0172                     memcpy(map[i].req, map[i].th, sizeof(ndrx_debug_t));
0173                     ndrx_debug_addref(map[i].req->dbg_f_ptr);
0174                 }
0175                 else
0176                 {
0177                     /* Copy from TPlog: locking against proc level tplogconfig changes */
0178                     MUTEX_LOCK_V(M_proc_lock);
0179                     memcpy(map[i].req, map[i].proc, sizeof(ndrx_debug_t));
0180                     MUTEX_UNLOCK_V(M_proc_lock);
0181                     ndrx_debug_addref(map[i].req->dbg_f_ptr);
0182                 }
0183     
0184                 /* restore the fields... */
0185                 LOGGER_RESTORE_FIELDS(map[i].req);
0186                 dosetup=EXTRUE;
0187             }
0188             else if (0!=strcmp(map[i].req->filename, filename))
0189             {
0190                 dosetup=EXTRUE;
0191             }
0192         }
0193 
0194         /* setup only once, if was setup, ignore the function call */
0195         /* copy off the pointers, use the same file pointer... */
0196         if (dosetup)
0197         {
0198             for (i=0; i<3; i++)
0199             {
0200                 /* register sinks for each of the loggers, inherit the flags, if any...
0201                  * What here we can inherit mkdir & flock
0202                  *  
0203                  */
0204                 /* switch loggers if any...  */
0205                 
0206                 if (NULL==map[i].req->dbg_f_ptr)
0207                 {
0208                     ndrx_debug_get_sink(filename, EXTRUE, map[i].req, NULL);
0209                 }
0210                 else
0211                 {
0212                     /* leave sink and open new name */
0213                     ndrx_debug_changename(filename, EXTRUE, map[i].req, NULL);
0214                 }
0215                 
0216                 /* set final name -?
0217                 NDRX_STRCPY_SAFE(map[i].req->filename, map[i].req->filename);
0218                  * */
0219 
0220             }
0221         }
0222     } while(0);
0223 }
0224 
0225 /**
0226  * Loop over the loggers and get the request one with full initialization
0227  * if required
0228  * @param logger code
0229  * @return logger found or NULL if invalid flag
0230  */
0231 exprivate ndrx_debug_t * ndrx_tplog_getlogger(int logger)
0232 {
0233     int i;
0234     ndrx_debug_t *ret = NULL;
0235     debug_map_t map[] = LOGGER_MAP;
0236     LOGGER_SAVE_FIELDS_DEF;
0237     
0238     for (i=0; i<N_DIM(map); i++)
0239     {
0240         if (logger & map[i].proc->flags)
0241         {
0242             ret = map[i].proc;
0243             break;
0244         }
0245         else if (logger & map[i].th->flags)
0246         {
0247             if (EXFAIL==map[i].th->level)
0248             {
0249                 LOGGER_SAVE_FIELDS(map[i].th);
0250 
0251                 /* thread logger inherits from base */
0252                 
0253                 /* locking against proc level*/
0254                 MUTEX_LOCK_V(M_proc_lock);
0255                 memcpy(map[i].th, map[i].proc, sizeof(ndrx_debug_t));
0256                 MUTEX_UNLOCK_V(M_proc_lock);
0257                 
0258                 /* increment usage
0259                  * proc is stable never removed, thus can surely reference it
0260                  * Also as proc is always is available we do not get
0261                  * here and do not deadlock.
0262                  */
0263                 ndrx_debug_addref(map[i].th->dbg_f_ptr);
0264                 
0265                 LOGGER_RESTORE_FIELDS(map[i].th);
0266                 
0267             }
0268             ret = map[i].th;
0269             break;
0270         }
0271         else if (logger & map[i].req->flags)
0272         {
0273             
0274             if (EXFAIL==map[i].req->level)
0275             {
0276                 LOGGER_SAVE_FIELDS(map[i].req);
0277 
0278                 /* request logger inherits from thread
0279                  * or from base - witch one is closer
0280                  */
0281                 if (NULL!=map[i].th->dbg_f_ptr)
0282                 {
0283                     memcpy(map[i].req, map[i].th, sizeof(ndrx_debug_t));
0284                     
0285                     /* our thread, thus logger always will have reference */
0286                     ndrx_debug_addref(map[i].req->dbg_f_ptr);
0287                 }
0288                 else
0289                 {
0290                     /* if somebody changes process level logger in some
0291                      * tread, have correct values down here.
0292                      */
0293                     MUTEX_LOCK_V(M_proc_lock);
0294                     memcpy(map[i].req, map[i].proc, sizeof(ndrx_debug_t));
0295                     MUTEX_UNLOCK_V(M_proc_lock);
0296                     
0297                     /* process loggers are never removed */
0298                     ndrx_debug_addref(map[i].req->dbg_f_ptr);
0299                 }
0300                 
0301                 LOGGER_RESTORE_FIELDS(map[i].req);
0302             }
0303             ret = map[i].req;
0304             break;
0305         }
0306     }
0307     
0308 out:
0309     return ret;
0310 }
0311 
0312 /**
0313  * Close the request file (back to other loggers)
0314  * This applies to all TP/NDRX/UBF facilities.
0315  * @param filename
0316  */
0317 expublic void tplogclosereqfile(void)
0318 {
0319     int i;
0320     /* Only if we have a TLS... */
0321     if (G_nstd_tls)
0322     {
0323         debug_map_t map[] = {
0324             {&G_nstd_tls->requestlog_tp}
0325             ,{&G_nstd_tls->requestlog_ndrx}
0326             ,{&G_nstd_tls->requestlog_ubf}
0327         };
0328         
0329         for (i=0; i<N_DIM(map); i++)
0330         {
0331             if (map[i].req->dbg_f_ptr)
0332             {
0333                 /* 
0334                  * OK we leave the sink
0335                  */
0336                 ndrx_debug_unset_sink(map[i].req->dbg_f_ptr, EXTRUE, EXFALSE);
0337                 map[i].req->dbg_f_ptr = NULL;
0338                 map[i].req->level = EXFAIL;
0339                 
0340             }
0341             map[i].req->filename[0] = EXEOS;
0342         }
0343     }
0344 }
0345 
0346 /**
0347  * Reconfigure loggers.
0348  * @param logger See LOG_FACILITY_*
0349  * @param lev 0..5 (if -1 (FAIL) then ignored)
0350  * @param config_line ndrx config line (if NULL/empty then ignored)
0351  * @param module 4 char module code (which uses the logger)
0352  * @param new_file New logging file (this overrides the stuff from debug string)
0353  * @return SUCCEED/FAIL
0354  */
0355 expublic int tplogconfig(int logger, int lev, const char *debug_string, const char *module, 
0356         const char *new_file)
0357 {
0358     return tplogconfig_int(logger, lev, debug_string, module, new_file, 0);
0359 }
0360 
0361 /**
0362  * Reconfigure loggers.
0363  * Due to fact that this covers also shared loggers, locking must be employed
0364  * i.e. process levels might be changed from other threads in the same time.
0365  * 
0366  * Well also other threads, might use the main logger as reference, it might
0367  * be changed concurrently (i.e. copy made). Thus those copy points
0368  * shall be protected too against these changes.
0369  * 
0370  * @param logger See LOG_FACILITY_*
0371  * @param lev 0..5 (if -1 (FAIL) then ignored)
0372  * @param config_line ndrx config line (if NULL/empty then ignored)
0373  * @param module 4 char module code (which uses the logger)
0374  * @param new_file New logging file (this overrides the stuff from debug string)
0375  * @param flags internal flags
0376  * @return SUCCEED/FAIL
0377  */
0378 expublic int tplogconfig_int(int logger, int lev, const char *debug_string, const char *module, 
0379         const char *new_file, long flags)
0380 {
0381     int ret = EXSUCCEED;
0382     ndrx_debug_t *l;
0383     char tmp_filename[PATH_MAX+1];
0384     int loggers[] = {LOG_FACILITY_NDRX, 
0385                     LOG_FACILITY_UBF, 
0386                     LOG_FACILITY_TP,
0387                     LOG_FACILITY_TP_THREAD,
0388                     LOG_FACILITY_TP_REQUEST,
0389                     LOG_FACILITY_NDRX_THREAD,
0390                     LOG_FACILITY_NDRX_REQUEST,
0391                     LOG_FACILITY_UBF_THREAD,
0392                     LOG_FACILITY_UBF_REQUEST    
0393     };
0394     int i;
0395     
0396     API_ENTRY; /* set TLS too, might pull in other thread not working under the TLS */
0397     NDRX_DBG_INIT_ENTRY; /* Do the debug entry (so that we load defaults...) */
0398  
0399     for (i=0; i<N_DIM(loggers); i++)
0400     {
0401         int curlogger = logger & loggers[i];
0402 
0403         if (!curlogger)
0404         {
0405             continue;
0406         }
0407         
0408         l = ndrx_tplog_getlogger(curlogger);
0409 
0410         if (NULL==l)
0411         {
0412             /*
0413             _Nset_error_fmt(NEINVAL, "tplogconfig: Invalid logger: %d", logger);
0414             FAIL_OUT(ret);
0415              */
0416             continue;
0417         }
0418         
0419         /* If this is process level logger, do the locking... */
0420         if (l->flags & LOG_FACILITY_PROCESS)
0421         {
0422             MUTEX_LOCK_V(M_proc_lock);
0423         }
0424 
0425         if (NULL!=module && EXEOS!=module[0] && 
0426                 loggers[i] != LOG_FACILITY_NDRX &&
0427                 loggers[i] != LOG_FACILITY_UBF &&
0428                 loggers[i] != LOG_FACILITY_NDRX_THREAD &&
0429                 loggers[i] != LOG_FACILITY_UBF_THREAD &&
0430                 loggers[i] != LOG_FACILITY_NDRX_REQUEST &&
0431                 loggers[i] != LOG_FACILITY_UBF_REQUEST
0432             )
0433         {
0434             NDRX_STRNCPY(l->module, module, 4);
0435             l->module[4] = EXEOS;
0436         }
0437 
0438         if (NULL!= debug_string && EXEOS!=debug_string[0])
0439         {
0440             /* parse out the logger 
0441              * Check if file is changed? If changed, then we shall
0442              * close the old file & open newone...
0443              */
0444             NDRX_STRCPY_SAFE(tmp_filename, l->filename);
0445             
0446             if (EXSUCCEED!= (ret = ndrx_init_parse_line(debug_string, l, 
0447                     l->filename, sizeof(l->filename), NULL, NULL )))
0448             {
0449                 
0450                 /* unlock process lev */
0451                 if (l->flags & LOG_FACILITY_PROCESS)
0452                 {
0453                     MUTEX_UNLOCK_V(M_proc_lock);
0454                 }
0455                 
0456                 _Nset_error_msg(NEFORMAT, "Failed to parse debug string");
0457                 EXFAIL_OUT(ret);
0458             }
0459 
0460             /* only if new name is not passed in */
0461             if (0!=strcmp(tmp_filename, l->filename) && 
0462                     (NULL==new_file || EXEOS==new_file[0]))
0463             {
0464                 ndrx_debug_changename(l->filename, EXTRUE, l, NULL);
0465             }
0466             
0467             /* assume running in single thread only... */
0468             if (flags & NDRX_TPLOGCONFIG_VERSION_INC)
0469             {
0470                 /* so that threads/request loggers can copy the levels
0471                  * if version does not match
0472                  */
0473                 l->version++;
0474             }
0475         }
0476 
0477         if (EXFAIL!=lev)
0478         {
0479             l->level = lev;
0480         }
0481         
0482         /* new file passed in: */
0483         if (NULL!=new_file && EXEOS!=new_file[0] && 0!=strcmp(new_file, l->filename))
0484         {            
0485             ndrx_debug_changename(new_file, EXTRUE, l, NULL);
0486         }
0487         
0488         /* unlock process lev */
0489         if (l->flags & LOG_FACILITY_PROCESS)
0490         {
0491             MUTEX_UNLOCK_V(M_proc_lock);
0492         }
0493 
0494     }
0495     
0496 out:
0497     return ret;
0498 }
0499 
0500 /**
0501  * Reopen log handles (may be used after log files are rotated)
0502  */
0503 expublic int tplogreopen(void)
0504 {
0505     API_ENTRY;
0506     NDRX_DBG_INIT_ENTRY;
0507     return ndrx_debug_reopen_all();
0508 }
0509 
0510 /**
0511  * Close thread logger (if open)
0512  */
0513 expublic void tplogclosethread(void)
0514 {
0515     int i;
0516     /* Only if we have a TLS... */
0517     if (G_nstd_tls)
0518     {
0519         debug_map_t map[] = {
0520             {&G_nstd_tls->threadlog_tp}
0521             ,{&G_nstd_tls->threadlog_ubf}
0522             ,{&G_nstd_tls->threadlog_ndrx}
0523         };
0524         
0525         for (i=0; i<N_DIM(map); i++)
0526         {
0527             if (map[i].req->dbg_f_ptr)
0528             {
0529                 /* 
0530                  * OK we leave the sink
0531                  */
0532                 ndrx_debug_unset_sink(map[i].req->dbg_f_ptr, EXTRUE, EXFALSE);
0533                 map[i].req->dbg_f_ptr = NULL;
0534                 map[i].req->level = EXFAIL;
0535                 
0536             }
0537             map[i].req->filename[0] = EXEOS;
0538         }
0539     }
0540 }
0541 
0542 /**
0543  * Get the current request file
0544  * @param filename (optional) optional to return file name
0545  * @return TRUE (request file used) / FALSE (request file not used)
0546  */
0547 expublic int tploggetreqfile(char *filename, int bufsize)
0548 {
0549     int ret = EXFALSE;
0550     
0551     if (NULL==G_nstd_tls->requestlog_tp.dbg_f_ptr)
0552     {
0553         ret=EXFALSE;
0554         goto out;
0555     }
0556     
0557     ret = EXTRUE;
0558 
0559     if (NULL!=filename)
0560     {
0561         if (bufsize>0)
0562         {
0563             NDRX_STRCPY_SAFE_DST(filename, G_nstd_tls->requestlog_tp.filename, bufsize);
0564         }
0565         else
0566         {
0567             strcpy(filename, G_nstd_tls->requestlog_tp.filename);
0568         }
0569     }
0570     
0571 out:
0572     return ret;
0573 }
0574 
0575 /**
0576  * Log the message to configured device
0577  * @param lev
0578  * @param message
0579  */
0580 expublic void tplog(int lev, const char *message)
0581 {
0582     /* do not want to interpret the format string */
0583     TP_LOG(lev, "%s", message);
0584 }
0585 
0586 /**
0587  * Extended logging (TP)
0588  * @param lev
0589  * @param message
0590  */
0591 expublic void tplogex(int lev, const char *file, long line, const char *message)
0592 {
0593     /* do not want to interpret the format string */
0594     TP_LOGEX(lev, file, line, "%s", message);
0595 }
0596 
0597 /**
0598  * Get integration flags
0599  * @return integration flags set (EOS or some infos from debug config)
0600  */
0601 expublic char * tploggetiflags(void)
0602 {
0603     TP_LOGGETIFLAGS;
0604 }
0605 
0606 /**
0607  * Do the hex dump
0608  * @param lev
0609  * @param comment
0610  * @param ptr
0611  * @param len
0612  */
0613 expublic void tplogdump(int lev, const char *comment, void *ptr, int len)
0614 {
0615     TP_DUMP(lev, comment, (char *)ptr, len);
0616 }
0617 
0618 /**
0619  * Print the differences of to binary arrays
0620  * @param lev
0621  * @param comment
0622  * @param ptr1
0623  * @param ptr2
0624  * @param len
0625  */
0626 expublic void tplogdumpdiff(int lev, const char *comment, void *ptr1, void *ptr2, int len)
0627 {
0628     TP_DUMP_DIFF(lev, comment, (char *)ptr1, (char *)ptr2, len);
0629 }
0630  
0631 /**
0632  * Log the message to configured device, ndrx facility
0633  * @param lev
0634  * @param message
0635  */
0636 expublic void ndrxlog(int lev, const char *message)
0637 {
0638     /* do not want to interpret the format string */
0639     NDRX_LOG(lev, "%s", message);
0640 }
0641 
0642 /**
0643  * Extended logging (NDRX)
0644  * @param lev log level
0645  * @param file source file name
0646  * @param line source line number
0647  * @param message log message
0648  */
0649 expublic void ndrxlogex(int lev, const char *file, long line, const char *message)
0650 {
0651     /* do not want to interpret the format string */
0652     NDRX_LOGEX(lev, file, line, "%s", message);
0653 }
0654 
0655 /**
0656  * Do the hex dump, ndrx facility
0657  * @param lev
0658  * @param comment
0659  * @param ptr
0660  * @param len
0661  */
0662 expublic void ndrxlogdump(int lev, const char *comment, void *ptr, int len)
0663 {
0664     NDRX_DUMP(lev, comment, (char *)ptr, len);
0665 }
0666 
0667 /**
0668  * Print the differences of to binary arrays, ndrx facility
0669  * @param lev
0670  * @param comment
0671  * @param ptr1
0672  * @param ptr2
0673  * @param len
0674  */
0675 expublic void ndrxlogdumpdiff(int lev, const char *comment, void *ptr1, void *ptr2, int len)
0676 {
0677     NDRX_DUMP_DIFF(lev, comment, (char *)ptr1, (char *)ptr2, len);
0678 }
0679  
0680 /**
0681  * Log the message to configured device, ubf facility
0682  * @param lev
0683  * @param message
0684  */
0685 expublic void ubflog(int lev, const char *message)
0686 {
0687     /* do not want to interpret the format string */
0688     UBF_LOG(lev, "%s", message);
0689 }
0690 
0691 /**
0692  * Extended logging (UBF)
0693  * @param lev log level
0694  * @param file source file name
0695  * @param line source line number
0696  * @param message log message
0697  */
0698 expublic void ubflogex(int lev, const char *file, long line, const char *message)
0699 {
0700     /* do not want to interpret the format string */
0701     UBF_LOGEX(lev, file, line, "%s", message);
0702 }
0703 
0704 /**
0705  * Do the hex dump, ubf facility
0706  * @param lev
0707  * @param comment
0708  * @param ptr
0709  * @param len
0710  */
0711 expublic void ubflogdump(int lev, const char *comment, void *ptr, int len)
0712 {
0713     UBF_DUMP(lev, comment, (char *)ptr, len);
0714 }
0715 
0716 /**
0717  * Print the differences of to binary arrays, ubf facility
0718  * @param lev
0719  * @param comment
0720  * @param ptr1
0721  * @param ptr2
0722  * @param len
0723  */
0724 expublic void ubflogdumpdiff(int lev, const char *comment, void *ptr1, void *ptr2, int len)
0725 {
0726     UBF_DUMP_DIFF(lev, comment, (char *)ptr1, (char *)ptr2, len);
0727 }
0728 
0729 /**
0730  * TPLOG Query Information
0731  * Oldest byte (signed) is log level, next TPLOGQI flags, then log facility follows
0732  * Feature #312
0733  * @lev debug level (normally 1..5, 6 - dump)
0734  * @flags see TPLOGQI_GET flags
0735  * @return signed 32bit integer
0736  */
0737 expublic long tplogqinfo(int lev, long flags)
0738 {
0739     int ret  = 0;
0740     int tmp;
0741     ndrx_debug_t *dbg;
0742     
0743     API_ENTRY;
0744     
0745     if (flags & TPLOGQI_GET_NDRX)
0746     {
0747         dbg = debug_get_ndrx_ptr();
0748     }
0749     else if (flags & TPLOGQI_GET_UBF)
0750     {
0751         dbg = debug_get_ubf_ptr();
0752     }
0753     else if (flags & TPLOGQI_GET_TP)
0754     {
0755         dbg = debug_get_tp_ptr();
0756     }
0757     else 
0758     {
0759         _Nset_error_fmt(NEINVAL, "%s: Invalid flags: %ld", __func__, flags);
0760         EXFAIL_OUT(ret);
0761     }
0762     
0763     if (!(flags & TPLOGQI_EVAL_RETURN) && lev > dbg->level)
0764     {
0765         goto out;
0766     }
0767     
0768     ret|=(((int)dbg->flags) & LOG_FACILITY_MASK);
0769     
0770     if (flags & TPLOGQI_EVAL_DETAILED)
0771     {
0772         if (NULL!=strstr(dbg->iflags, LOG_IFLAGS_DETAILED))
0773         {
0774             ret|=TPLOGQI_RET_HAVDETAILED;
0775         }
0776     }
0777     tmp = dbg->level;
0778     
0779     tmp <<= TPLOGQI_RET_DBGLEVBITS;
0780     ret|=tmp;
0781     
0782 out:
0783             
0784     return ret;
0785 }
0786 
0787 /**
0788  * Lock current TPLOG handler for given thread.
0789  * @param lev log level request (or -1 return fd anyway)
0790  * @param flags RFU
0791  * @return debug handle or NULL in case if no logging is required
0792  */
0793 expublic ndrx_debug_t * tplogfplock(int lev, long flags)
0794 {
0795     ndrx_debug_t * ret = debug_get_tp_ptr();
0796 
0797     if (ret->level>=lev || EXFAIL==lev)
0798     {
0799         ndrx_debug_lock((ndrx_debug_file_sink_t*)ret->dbg_f_ptr);
0800         return (void *)ret;
0801     }
0802 
0803     /* no handle as level not passed */
0804     return NULL;
0805 }
0806 
0807 /**
0808  * Get debug handle
0809  * @param flags RFU
0810  * @param dbg handle returned from tplogfplock()
0811  * @return file handle
0812  */
0813 expublic FILE *tplogfpget(ndrx_debug_t *dbg, long flags)
0814 {
0815     if (NULL==dbg)
0816     {
0817         return NULL;
0818     }
0819 
0820     return ((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr)->fp;
0821 }
0822 
0823 /**
0824  * Unlock the debug handle
0825  * @param dbg debug handle returned by tplogfplock()
0826  */
0827 expublic void tplogfpunlock(ndrx_debug_t *dbg)
0828 {
0829     if (NULL==dbg)
0830     {
0831         return;
0832     }
0833 
0834     ndrx_debug_unlock((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr);    
0835 }
0836 
0837 /* vim: set ts=4 sw=4 et smartindent: */