// // File: hzProcess.h // // Legal Notice: This file is part of the HadronZoo C++ Class Library. // // Copyright 2025 HadronZoo Project (http://www.hadronzoo.com) // // The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free // Software Foundation, either version 3 of the License, or any later version. // // The HadronZoo C++ Class Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR // A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses. //
#ifndef hzProcess_h #define hzProcess_h
#include "hzDate.h" #include "hzLock.h" #include "hzString.h"
/* ** SECTION 1: The hzProcess and hzProginfo classes */
class hzLogger ;
class hzProcess { // Category: System // // The hzProcess class holds information on the current thread. This is for the purpose of directing log messages and facilitating stack traces. An instance of hzProcess per // thread is COMPULSORY in all programs based on the HadronZoo library, including single threaded programs.
class _fncall_rec { // Record of a function call
public: const char* m_func ; // Function full name (class::fnname) uint32_t m_callNo ; // Sequence number uint16_t m_series ; // Number of times sequence flipped back to zero uint16_t m_callLevel ; // Call depth of call
_fncall_rec () { m_func = 0 ; m_callNo = 0 ; m_series = m_callLevel = 0 ; } } ;
const char** m_Stack ; // Function call stack _fncall_rec* m_Hist ; // Recent function call history
hzLogger* m_pLog ; // The default (first) logger for the thread void* m_CurrentLock ; // Memory location Microlock pthread_t m_TID ; // The current thread id hzString m_LastErrmsg ; // Last error message in current thread uint32_t m_Id ; // Short form ID (based on position in the global array of hzProcess instances) uint32_t m_nFuncs ; // The current function (current position in stack) uint32_t m_nPeak ; // Function depth high water mark uint32_t m_nSeqCall ; // Function call sequence number uint32_t m_nCallOset ; // Current offset into history uint32_t m_nScratchOset ; // Current offset into scratch buffer (after allocation) uint32_t m_nScratchAdvn ; // Current offset into scratch buffer (before allocation) hzEcode m_LastEcode ; // Last error code char m_Scratch[16384] ; // Scratch pad
static void _register (hzProcess* pProc) ; static void _deregister (hzProcess* pProc) ;
public: hzProcess (void) ; ~hzProcess (void) ;
// Set the default logger for the thread to the supplied logger unless already set void SetLog (hzLogger* pLog) { m_pLog = pLog ; }
hzLogger* GetLog (void) { return m_pLog ; } // Get logger for thread pthread_t GetTID (void) { return m_TID ; } // Get the thread id uint32_t GetId (void) { return m_Id ; } // Get the short form thread id uint32_t Level (void) { return m_nFuncs-1 ; } // Return current function call level
const char* GetCurrFunc (void) { if (m_nFuncs > 0) return m_Stack[m_nFuncs-1] ; return 0 ; }
void PushFunction (const char* funcname) ; // Notify thread stack of function call void PullFunction (void) ; // Notify thread of function return void StackTrace (void) ; // Export Current Stack Trace void CallHistory (void) ; // Export recent function call history char* ScratchPad (int32_t nSize) ; // Provide a temporary non-deletable buffer for values (to feed to printf type functions) } ;
class hzProginfo { // Category: System // // Information on currently running program - as held in the /proc directory.
public: hzString m_Progname ; // Name of program hzString m_Executable ; // Full path to the executable uint32_t m_PID ; // Process ID (from proc) uint32_t m_Resv ; // Reserved } ;
/* ** SECTION 2: Shared Memory */
class hzShmem { // Category: System // // Shared memory segment for Inter-process Communication.
void* m_pStart ; // Pointer to start hzString m_name ; // Shared memory segment name uint32_t m_size ; // Shared memory segment size uint32_t m_perm ; // Access permissions uint32_t m_fd ; // Shared memory 'file descriptor' uint32_t m_resv ; // Reserved
public: hzShmem (void) { m_size = 0 ; m_pStart = 0 ; } ~hzShmem (void) {}
hzEcode Init (const char* name, uint32_t size, uint32_t mask) ; uint32_t Size (void) ;
void* GetMem (void) { return m_pStart ; } } ;
/* ** SECTION 3: Resource locking. The hzSysLock class */
class hzSysLock { // Category: System // // Controls 'external' resources such as files
int32_t m_nSemId ; // Unique id for semahore group int32_t m_lockval ; // The thread that has the lock uint32_t m_nResource ; // Slot within semaphore group uint32_t m_count ; // Number of nested calls to lock by same thread
void _init (void) ; // Obtain a semaphore from a semaphore set void _halt (void) ; // Free the semaphore back to the set (for possible reallocation) public: hzSysLock (void) { m_lockval = 0 ; m_count = 0 ; _init() ; }
~hzSysLock (void) { _halt() ; }
void Lock (void) ; void Unlock (void) ; } ;
/* ** SECTION 4: Event Loging Regime. This covers the following:- ** ** 1) Periodic log files ** 2) Dynamic debug levels ** 3) A naming regime to build function names into log output. ** 4) A protocol for loging via the HadronZoo logserver. ** 5) The hzLogger class for writing log output to. */
#define PORT_LOGSERVER 4592 #define HZ_LOGCHUNK 1449 // HZ_MAXPACKET - 11
enum hzLogRotate { // Category: Diagnostics // // Enum to control periodicity of roliing logfiles
LOGROTATE_NEVER, // Never change logfile and truncate logfile at runtime LOGROTATE_OFLOW, // Change file when filesize reached 2GB (appname.log .. appname.1.log) LOGROTATE_YEAR, // Change logfile once per year appname_YYYY.log LOGROTATE_QTR, // Change logfile every quarter appname_YYYYQ?.log LOGROTATE_MONTH, // Change logfile every month appname_YYYYMM.log LOGROTATE_MON, // Change logfile every Monday appname_YYYYMMDDMon.log LOGROTATE_TUE, // Change logfile every Tuesday appname_YYYYMMDDTue.log LOGROTATE_WED, // Change logfile every Wednesday appname_YYYYMMDDWed.log LOGROTATE_THR, // Change logfile every Thursday appname_YYYYMMDDThr.log LOGROTATE_FRI, // Change logfile every Friday appname_YYYYMMDDFri.log LOGROTATE_SAT, // Change logfile every Saturday appname_YYYYMMDDSat.log LOGROTATE_SUN, // Change logfile every Sunday appname_YYYYMMDDSun.log LOGROTATE_DAY, // Change logfile every day appname_YYYYMMDD.log LOGROTATE_12HR, // Change logfile every half day appname_YYYYMMDD?M.log LOGROTATE_HOUR, // Change logfile every hour appname_YYYYMMDDHH.log } ;
enum hzDebug { // Category: Diagnostics // // Controls which log messages are printed.
DEBUG_NONE = 0, // No debug messages (the default) DEBUG_LEVEL1 = 1, // Mega critical DEBUG_LEVEL2 = 2, // Importantish DEBUG_LEVEL3 = 3 // Trivial } ;
/* ** SECTION 5: Thread information prototypes */
hzProcess* GetThreadInfo (void) ; hzLogger* GetThreadLogger (void) ; void SetThreadLogger (hzLogger* plog) ;
class hzFuncname { // Category: Diagnostics // // hzFuncname is a const char pointer storing a function name. It was created as a class to avoid the compiler confusing it with anything else.
const char* m_pStr ; // Current function name
public: hzFuncname (void) { m_pStr = 0 ; } ~hzFuncname (void) { m_pStr = 0 ; }
void operator= (const char* fnName) { // Argument: fnName Sets the current function name // Returns: None
if (!m_pStr) m_pStr = fnName ; }
const char* operator* (void) const { return m_pStr ; } operator const char* (void) const { return m_pStr ; } } ;
class _hz_func_reg { // Category: Diagnostics // // Internal class to facilitate registration of a function call to the calling thread. The macro _hzfunc is placed at the top of most HadronZoo functions (both independent and // class members). This macro takes a char* argument, the value of which is assumed to be the fully qualified name of the function or a close variant of it. The macro declares // an instance of _hz_func_reg called _thisfn and assigns the function name to it. // // The _hz_func_reg assignment operator calls GetThreadInfo to obtain a pointer to the hzProcess instance for the current thread and stores in the the public member _phz. Then // it uses the pointer to call hzProcess::PushFunction - which pushes the function name on to the stack. // // In any function with the _hzfunc macro, the current thread is available without a further call to GetThreadInfo, as _thisfn._phz - not that a GetThreadInfo call is onerous. // The ready availablity of the hzProcess instance has a lot of potential for holding data 'private to the thread'. // // The _hzfunc macro must not be called outside the scope of a function even though the compiler would allow it. Doing so would place a false entry in the hzProcess stack. The // macro when called at the top of a function as intended, creates the _hz_func_reg instance _thisfn as an automatic variable. This is deleted when the function returns so the // call to hzProcess::PullFunction which pulls the function name from the hzProcess stack, is placed in the _hz_func_reg destructor.
public: hzProcess* _phz ; // Pointer to hzProcess instance (process information)
_hz_func_reg (void) { _phz = 0 ; }
~_hz_func_reg (void) { // This destructor is called as any function starting with a call to _hzfunc() ends. As the latter pushes a function name onto the function stack for // the thread, this must be pulled here.
if (_phz) _phz->PullFunction() ; }
void operator= (const char* fnName) { // Set the function name and push it onto the function stack for the thread. // // Argument: fnName The fully qualified function name // Returns: None
if (!_phz) _phz = GetThreadInfo() ;
if (_phz) _phz->PushFunction(fnName) ; }
char* ScratchPad (int32_t nSize) { if (!_phz) _phz = GetThreadInfo() ; return _phz->ScratchPad(nSize) ; } } ;
#define _hzfunc(x) static hzFuncname _fn ; _fn = x ; _hz_func_reg _thisfn ; _thisfn = *_fn #define _hzlevel() _thisfn._phz->Level()
// Specific to Collection Class Templates #define _hzfunc_ct(x) static hzFuncname _fn ; _fn = x ; _hz_func_reg _thisfn ; if (_hzGlobal_Debug & HZ_DEBUG_CTMPLS) _thisfn = *_fn
/* ** Error reporting prototypes */
hzEcode hzwarn (hzEcode eError, const char* va_alist ...) ; hzEcode hzerr (hzEcode eError, const char* va_alist ...) ; void hzexit (hzEcode eError, const char* va_alist ...) ; void Fatal (hzChain& error) ; void Fatal (const char* va_alist ...) ;
/* ** SECTION 6: Log signals to and from the HadronZoo logserver */
enum hzLogSignal { // Category: Diagnostics // // Commands to server
LS_NULL = 0, // No action LS_OPEN_PUB = 1, // Open a channel to a public logfile LS_OPEN_PVT = 2, // Open a channel to a private logfile LS_STOP = 3, // Close a channel (either public or private) LS_LOG = 4, // Log to a log file (either public or private)
// Server responses LS_ERR_CONN = 10, // Could not connect to logserver LS_ERR_SEND = 11, // Data could not be written to a socket LS_ERR_RECV = 12, // Date could not be read from a socket LS_ERR_PERM = 13, // Process does not have write permission LS_ERR_DUP = 14, // Channel already open LS_FAIL = 15, // Request failed LS_OK = 16, // Request succesful } ;
/* ** The LogChannel class */
class hzTcpClient ;
class hzLogger { // Category: Diagnostics // // The hzLogger class manages a 'log channel'. Instead of writing to a logfile applications write to a hzLogger instance. This // usually is a file but it might be a logserver instance (socket program)
// Variables for operation on direct files FILE* m_pFile ; // The active logfile hzLockS m_Lock ; // Mutex (if required) hzXDate m_datCurr ; // Current date & time hzXDate m_datLast ; // Last date & time rotation occured hzString m_Base ; // Basename of logfile hzString m_File ; // Full name of logfile
// Variables for operation with logserver hzTcpClient* m_pConnection ; // Connection as client to logserver uchar* m_pData ; // Buffer for preparation of log message uint16_t m_nIndent ; // No of tabs to indent uint16_t m_nSessID ; // Session ID
// Variable for both types of operation char* m_pDataPtr ; // Set at m_cvData or an offset to allow packet hdr hzLogRotate m_eRotate ; // Log rotate edict bool m_bVerbose ; // Send log messages to stdin as well as file char m_cvData[HZ_MAXPACKET+4] ; // Buffer for preparation of log message
void _logrotate (void) ; // Functions for operation on direct files hzEcode _write (uint32_t nBytes) ; // Internal write function
// Prevent copying hzLogger (const hzLogger& never) ; hzLogger& operator= (const hzLogger& never) ;
public: hzLogger (void) ; ~hzLogger (void) ;
void Verbose (bool bVerbose) { m_bVerbose = bVerbose ; } void SetIndent (uint16_t nIndent) { m_nIndent = nIndent ; }
bool IsOpen (void) { return m_Base || m_pFile || m_nSessID ? true : false ; } bool IsVerbose (void) { return m_bVerbose ; }
hzEcode OpenFile (const char* cpPath, hzLogRotate eRotate) ; hzEcode OpenPublic (const char* cpPath, hzLogRotate eRotate) ; hzEcode OpenPrivate (const char* cpPath, hzLogRotate eRotate, uint32_t Perms) ;
hzEcode Close (void) ; hzEcode Log (const hzChain& msg) ; hzEcode Log (const char* va_alist ...) ; hzEcode Out (const hzChain& msg) ; hzEcode Out (const char* va_alist ...) ;
hzLogger& operator<< (hzChain& Z) ; hzLogger& operator<< (hzString& Z) ; hzLogger& operator<< (const char* cpStr) ; } ;
hzEcode threadLog (const hzChain& msg) ; hzEcode threadLog (const char* va_alist ...) ; hzEcode threadOut (const hzChain& msg) ; hzEcode threadOut (const char* va_alist ...) ;
/* ** Globals */
extern __thread hzProcess* _hzGlobal_currProc ; // Process data for the current thread
extern hzString _hzGlobal_HOME ; // Environment variable $HOME extern hzString _hzGlobal_HADRONZOO ; // Environment variable $HADRONZOO extern hzString _hzGlobal_SysImages ; // HadronZoo system images extern uint32_t _hzGlobal_callStack_size ; // Depth of per-thread call stack extern uint32_t _hzGlobal_callHist_size ; // Depth of per-thread call history extern bool _hzGlobal_MT ; // Set true be set true by the application if it is to be run in multi-threaded mode extern bool _hzGlobal_kill ; // True if shutdown pending. Don't accept new connections.
/* ** Prototypes */
// Process control hzEcode HadronZooInitEnv (void) ; // Read environment variables $HOME and $HADRONZOO void Demonize (void) ; // Run the program as a demon void SingleProc (void) ; // Ensure singleton operation (prevent further program instances)
void StackTrace (void) ; // Log current stack trace for calling thread void CallHistory (void) ; // Log recent function call history for calling thread
void CatchSegVio (int32_t sig) ; // Provides backtrace of function calls in event of segment violation (SIGSEG) void CatchCtrlC (int32_t sig) ; // Catches Ctrl-C keypress (SIGINT)
// General Diagnostics hzEcode RegisterCollection (const hzString, void*) ; uint32_t ActiveThreadCount (void) ; void ReportMutexContention (hzChain& Z, bool bHtm) ; void ReportStringAllocations (hzChain& Z, bool bHtm) ; void ReportMemoryUsage (hzChain& Z, bool bHtm) ; void RecordMemoryUsage (bool bHtml=true) ;
#endif // hzProcess_h