// // File: hzLogger.cpp // // 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. //
// // Implimentation of the hzLogger class. //
#include <iostream>
#include <stdarg.h>
#include "hzChars.h" #include "hzChain.h" #include "hzIpServer.h" #include "hzTcpClient.h" #include "hzIpaddr.h" #include "hzProcess.h"
/* ** Variables */
static hzString s_LocalHost = "127.0.0.1" ; // This server IP address
/* ** hzLogger functios */
hzLogger::hzLogger (void) { // hzLogger constructor. Initialize logger, and set the logger for the thread to this logger.
m_pFile = 0 ; m_pDataPtr = m_cvData + 11 ; m_nIndent = 0 ; m_nSessID = 0 ; m_pConnection = 0 ; m_bVerbose = false ;
// Set the logger for the calling thread to be this locker SetThreadLogger(this) ; }
hzLogger::~hzLogger (void) { // hzLogger destructor. There is currently no de-registration facility. }
hzEcode hzLogger::OpenFile (const char* fpath, hzLogRotate eRotate) { // Purpose: Open a LogChannel to use a file regime // // Arguments: 1) fpath The logfile's base name or path // 2) eRotate The log rotate edict // // Returns: E_ARGUMENT If no file path is supplied // E_INITDUP If logger already open // E_OK If channel opened OK
_hzfunc("hzLogger::OpenFile") ;
char cvDir [HZ_MAXPATHLEN] ; // Current working directory char* cpCWD ; // Path iterator
if (!fpath || !fpath[0]) hzexit(E_ARGUMENT, "No path supplied") ;
if (IsOpen()) hzexit(E_INITDUP, "%s: This log channel is already open", fpath) ;
if (fpath[0] == CHAR_FWSLASH) m_Base = fpath ; else { cpCWD = getcwd(cvDir, HZ_MAXPATHLEN) ; for (; *cpCWD ; cpCWD++) ; *cpCWD++ = CHAR_FWSLASH ; strcpy(cpCWD, fpath) ; m_Base = cvDir ; }
// Set this to non zero to indicate channel open m_nSessID = 0 ;
// Set rotate edict m_eRotate = eRotate ;
// Set data pointer m_pDataPtr = m_cvData ;
return E_OK ; }
hzEcode hzLogger::OpenPublic (const char* fpath, hzLogRotate eRotate) { // Purpose: Open a LogChannel to use a public logfile // // Arguments: 1) fpath The logfile's publicly known path which must be in /etc/logserver.d/public_logs.conf // 2) eRotate The log rotate edict // // Returns: E_HOSTFAIL If no connection to the logserver could be established // E_SENDFAIL If the open command could not be sent to the logserver // E_RECVFAIL If the logserver's response could not be received // E_WRITEFAIL If the logserver fails to find the named public logfile // E_PROTOCOL If the uid of the calling process is not permitted to write to the file // E_OK If the logserver has opened a channel to the named public logfile
_hzfunc("hzLogger::OpenPublic") ;
uint32_t nSize ; // Size of logserver client request uint32_t nUsr ; // UNIX user id uint32_t nGrp ; // UNIX group id uint32_t nProcID ; // Caller process id uchar* u ; // Pointer into message buffer
// Connect to the logserver
m_pConnection = new hzTcpClient() ;
if (m_pConnection->ConnectStd(s_LocalHost, PORT_LOGSERVER) != E_OK) return E_HOSTFAIL ;
// Prepare header
nSize = 16 + strlen(fpath) ; nProcID = getpid() ; nUsr = geteuid() ; nGrp = getegid() ;
u = (uchar*) m_cvData ;
// Command u[0] = LS_OPEN_PUB ;
// Size of message u[1] = (nSize & 0xff00) >> 8 ; u[2] = (nSize & 0xff) ;
// Process ID u[3] = (nProcID & 0xff000000) >> 24 ; u[4] = (nProcID & 0xff0000) >> 16 ; u[5] = (nProcID & 0xff00) >> 8 ; u[6] = (nProcID & 0xff) ;
// User ID u[7] = (nUsr & 0xff000000) >> 24 ; u[8] = (nUsr & 0xff0000) >> 16 ; u[9] = (nUsr & 0xff00) >> 8 ; u[10] = (nUsr & 0xff) ;
// Group ID u[11] = (nGrp & 0xff000000) >> 24 ; u[12] = (nGrp & 0xff0000) >> 16 ; u[13] = (nGrp & 0xff00) >> 8 ; u[14] = (nGrp & 0xff) ;
// Filename strncpy(m_cvData + 15, fpath, HZ_MAXPATHLEN) ;
// Send message and recv response
if (m_pConnection->Send(m_cvData, nSize) != E_OK) return E_SENDFAIL ;
if (m_pConnection->Recv(m_cvData, nSize, 64) != E_OK) return E_RECVFAIL ;
if (nSize == 4 && m_cvData[0] == LS_OK) { m_nSessID = 0 ; m_nSessID |= (u[1] << 16) ; m_nSessID |= (u[2] << 8) ; m_nSessID |= u[3] ; return E_OK ; }
if (m_cvData[0] == LS_ERR_PERM) return E_WRITEFAIL ;
// Set data pointer m_pDataPtr = m_cvData + 10 ; return E_PROTOCOL ; }
hzEcode hzLogger::OpenPrivate (const char* fpath, hzLogRotate eRotate, uint32_t nPerms) { // Purpose: Open a LogChannel to use a private logserver file // // Arguments: 1) fpath The base pathname of the logfile // 2) eRotate The log rotate edict // 3) nPerms Access permissions to be applied to the file. This will be ignored by the logserver if the file already exists and the calling // process has write permission. // // Returns: E_HOSTFAIL If no connection to the logserver could be established // E_SENDFAIL If the open command could not be sent to the logserver // E_RECVFAIL If the logserver's response could not be received // E_WRITEFAIL If the logserver fails to find the named public logfile // E_PROTOCOL If the uid of the calling process is not permitted to write to the file // E_OK If the logserver has opened a channel to the named public logfile
_hzfunc("hzLogger::OpenPrivate") ;
uint32_t nSize ; // Size of logserver client request uint32_t nUsr ; // UNIX user id uint32_t nGrp ; // UNIX group id uint32_t nProcID ; // Caller process id uchar* u ; // Pointer into message buffer
// Connect to the logserver
if (m_pConnection->ConnectStd(s_LocalHost, PORT_LOGSERVER) != E_OK) return E_HOSTFAIL ;
// Prepare header
nSize = 21 + strlen(fpath) ; nProcID = getpid() ; nUsr = geteuid() ; nGrp = getegid() ;
u = (uchar*) m_cvData ;
// Command u[ 0] = LS_OPEN_PUB ;
// Size of message u[ 1] = (nSize & 0xff00) >> 8 ; u[ 2] = (nSize & 0xff) ;
// Process ID u[ 3] = (nProcID & 0xff000000) >> 24 ; u[ 4] = (nProcID & 0xff0000) >> 16 ; u[ 5] = (nProcID & 0xff00) >> 8 ; u[ 6] = (nProcID & 0xff) ;
// User ID u[ 7] = (nUsr & 0xff000000) >> 24 ; u[ 8] = (nUsr & 0xff0000) >> 16 ; u[ 9] = (nUsr & 0xff00) >> 8 ; u[10] = (nUsr & 0xff) ;
// Group ID u[11] = (nGrp & 0xff000000) >> 24 ; u[12] = (nGrp & 0xff0000) >> 16 ; u[13] = (nGrp & 0xff00) >> 8 ; u[14] = (nGrp & 0xff) ;
// Permissions u[15] = (nPerms & 0xff000000) >> 24 ; u[16] = (nPerms & 0xff0000) >> 16 ; u[17] = (nPerms & 0xff00) >> 8 ; u[18] = (nPerms & 0xff) ;
// Rotate edict u[19] = eRotate ;
// Filename strncpy(m_cvData + 20, fpath, HZ_MAXPATHLEN) ;
// Send message and recv response
if (m_pConnection->Send(m_cvData, nSize) != E_OK) return E_SENDFAIL ;
if (m_pConnection->Recv(m_cvData, nSize, 64) != E_OK) return E_RECVFAIL ;
if (nSize == 4 && m_cvData[0] == LS_OK) { m_nSessID = 0 ; m_nSessID |= (u[1] << 16) ; m_nSessID |= (u[2] << 8) ; m_nSessID |= u[3] ;
// Set data pointer m_pDataPtr = m_cvData + 10 ;
return E_OK ; }
return E_PROTOCOL ; }
hzEcode hzLogger::Close (void) { // Close a log channel and remove it from the thread-logger table. // // Arguments: None // // Returns: E_SENDFAIL If the open command could not be sent to the logserver // E_RECVFAIL If the logserver's response could not be received // E_PROTOCOL If the uid of the calling process is not permitted to write to the file // E_OK If the log channel was successfully closed
_hzfunc("hzLogger::Close") ;
uint32_t nBytes ; // Size of logserver client request uint32_t nProcID ; // Caller process id uchar* u ; // Pointer into message buffer
if (m_File) { // Log channel is using a direct file
if (m_pFile) fclose(m_pFile) ; m_pFile = 0 ; m_nSessID = 0 ; m_Base.Clear() ; m_File.Clear() ; return E_OK ; }
// Log channel is using the logserver
u = (uchar*) m_cvData ; nProcID = getpid() ;
// Command u[0] = LS_STOP ;
// Size of message is 8 bytes u[1] = 0 ; u[2] = 8 ;
// Session ID u[3] = (m_nSessID & 0x00ff0000) >> 16 ; u[4] = (m_nSessID & 0x0000ff00) >> 8 ; u[5] = (m_nSessID & 0x000000ff) ;
// Proc ID (not applicable) u[6] = (nProcID & 0xff00) >> 8 ; u[7] = (nProcID & 0xff00) >> 8 ; u[8] = (nProcID & 0xff00) >> 8 ; u[9] = (nProcID & 0xff) ; nBytes = 10 ;
// Send message and receive response
if (m_pConnection->Send(m_cvData, nBytes) != E_OK) return E_SENDFAIL ;
if (m_pConnection->Recv(m_cvData, nBytes, 64) != E_OK) return E_RECVFAIL ;
if (m_cvData[0] == LS_OK) return E_OK ; return E_PROTOCOL ; }
void hzLogger::_logrotate (void) { // Private method to change the hzLogger output file so as to seperate logfiles into approapriate time periods. // // Arguments: None // Returns: None
_hzfunc("hzLogger::_logrotate") ;
bool bChange = false ; // Log rotation on/off indicator char buf [32] ; // Log filename buffer
m_datCurr.SysDateTime() ;
switch (m_eRotate) { case LOGROTATE_NEVER: bChange = (m_Base && m_pFile == 0) ; break ; case LOGROTATE_OFLOW: bChange = (m_Base && m_pFile == 0) ; break ;
case LOGROTATE_YEAR: bChange = (m_datCurr.Year() != m_datLast.Year()) ; break ; case LOGROTATE_QTR: bChange = ((m_datCurr.Month() / 3) != (m_datLast.Month() / 3)) ; break ; case LOGROTATE_MONTH: bChange = (m_datCurr.Month() != m_datLast.Month()) ; break ;
case LOGROTATE_MON: bChange = (m_datCurr.NoDays() != m_datLast.NoDays() && m_datCurr.Dow() == 0) ; break ; case LOGROTATE_TUE: bChange = (m_datCurr.NoDays() != m_datLast.NoDays() && m_datCurr.Dow() == 1) ; break ; case LOGROTATE_WED: bChange = (m_datCurr.NoDays() != m_datLast.NoDays() && m_datCurr.Dow() == 2) ; break ; case LOGROTATE_THR: bChange = (m_datCurr.NoDays() != m_datLast.NoDays() && m_datCurr.Dow() == 3) ; break ; case LOGROTATE_FRI: bChange = (m_datCurr.NoDays() != m_datLast.NoDays() && m_datCurr.Dow() == 4) ; break ; case LOGROTATE_SAT: bChange = (m_datCurr.NoDays() != m_datLast.NoDays() && m_datCurr.Dow() == 5) ; break ; case LOGROTATE_SUN: bChange = (m_datCurr.NoDays() != m_datLast.NoDays() && m_datCurr.Dow() == 6) ; break ;
case LOGROTATE_DAY: bChange = (m_datCurr.NoDays() != m_datLast.NoDays()) ; break ; case LOGROTATE_12HR: bChange = ((m_datCurr.Hour() / 12) != (m_datLast.Hour() / 12)) ; break ; case LOGROTATE_HOUR: bChange = (m_datCurr.Hour() != m_datLast.Hour()) ; break ; }
if (!bChange && m_pFile == 0 && *m_Base) bChange = true ;
if (bChange) { m_datLast = m_datCurr ; if (m_pFile) fclose(m_pFile) ;
switch (m_eRotate) { case LOGROTATE_NEVER: sprintf(buf, ".log") ; break ; case LOGROTATE_OFLOW: sprintf(buf, ".log") ; break ;
case LOGROTATE_YEAR: sprintf(buf, "_%04d.log", m_datCurr.Year()) ; break ; case LOGROTATE_QTR: sprintf(buf, "_%04dQ%d.log", m_datCurr.Year(), (m_datCurr.Month()/3) + 1) ; break ; case LOGROTATE_MONTH: sprintf(buf, "_%04d%02d.log", m_datCurr.Year(), m_datCurr.Month()) ; break ;
case LOGROTATE_MON: sprintf(buf, "_%04d%02d%02dMon.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day()) ; break ; case LOGROTATE_TUE: sprintf(buf, "_%04d%02d%02dTue.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day()) ; break ; case LOGROTATE_WED: sprintf(buf, "_%04d%02d%02dWed.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day()) ; break ; case LOGROTATE_THR: sprintf(buf, "_%04d%02d%02dThr.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day()) ; break ; case LOGROTATE_FRI: sprintf(buf, "_%04d%02d%02dFri.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day()) ; break ; case LOGROTATE_SAT: sprintf(buf, "_%04d%02d%02dSat.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day()) ; break ; case LOGROTATE_SUN: sprintf(buf, "_%04d%02d%02dSun.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day()) ; break ; case LOGROTATE_DAY: sprintf(buf, "_%04d%02d%02d.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day()) ; break ;
case LOGROTATE_12HR: sprintf(buf, "_%04d%02d%02d%s.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day(), m_datCurr.Hour() > 11 ? "PM" : "AM") ; break ;
case LOGROTATE_HOUR: sprintf(buf, "_%04d%02d%02d%02d.log", m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day(), m_datCurr.Hour()) ; break ; }
m_File = m_Base ; m_File += buf ;
if (m_eRotate == LOGROTATE_NEVER) m_pFile = fopen(*m_File, "w") ; else m_pFile = fopen(*m_File, "a") ;
if (!m_pFile) { std::cout << "Cannot open logfile [" << m_File << "] Terminating process\n" ; exit(-1) ; } } }
hzEcode hzLogger::_write (uint32_t nBytes) { // Private support function to unify logfile writing to either a logfile or a virtual logfile managed by the logserver. // // Arguments: 1) nBytes Number of bytes to write // // Returns: E_SENDFAIL If the open command could not be sent to the logserver // E_RECVFAIL If the logserver's response could not be received // E_PROTOCOL If the uid of the calling process is not permitted to write to the file // E_OK If the log channel was successfully closed
_hzfunc("hzLogger::_write") ;
uint32_t nSize ; // Size of logserver client request uint32_t nProcID ; // Caller process id
// If log channel not open just return if (!IsOpen()) return E_OK ;
/* ** If log channel is using a direct file */
if (m_nSessID == 0) { /* if (m_bVerbose) { std::cout.write(m_pDataPtr, nBytes) ; fflush(stdout) ; } */
if (m_pFile) { fwrite(m_pDataPtr, nBytes, 1, m_pFile) ; fflush(m_pFile) ; }
return E_OK ; }
/* ** Log channel is using the logserver */
uchar* u = (uchar*) m_cvData ; // Pointer into logserver transport buffer
nSize = 11 + nBytes ; nProcID = getpid() ;
// Command u[0] = LS_LOG ;
// Size of message u[1] = (nSize & 0xff00) >> 8 ; u[2] = (nSize & 0xff) ;
// Session ID is 0 in this case u[3] = (m_nSessID & 0xff0000) >> 16 ; u[4] = (m_nSessID & 0xff00) >> 8 ; u[5] = (m_nSessID & 0xff) ;
// Process ID u[6] = (nProcID & 0xff00) >> 24 ; u[7] = (nProcID & 0xff00) >> 16 ; u[8] = (nProcID & 0xff00) >> 8 ; u[9] = (nProcID & 0xff) ;
// Send message
if (m_pConnection->Send(m_cvData, nSize) != E_OK) return E_SENDFAIL ;
if (m_pConnection->Recv(m_cvData, nSize, 64) != E_OK) return E_RECVFAIL ;
if (m_cvData[0] == LS_OK) return E_OK ; return E_PROTOCOL ; }
hzEcode hzLogger::Log (const char* va_alist ...) { // Log a variable argument message to the log channel. Deprecated as the hzFuncname class is to be reviewed. // // Arguments: va_alist Variable argument format string // // Returns: E_SENDFAIL If logging is to the logserver and could not be sent // E_RECVFAIL If logging is to the logserver and acknowledgemnt was not recieved // E_PROTOCOL If logging is to the logserver and said logserver did not observe protocol // E_OK If the log action was completed
//_hzfunc("hzLogger::Log") ;
va_list ap1 ; // Variable arguments list va_list ap2 ; // Copy of variable arguments list const char* fmt ; // Format control string uchar* u ; // Pointer into message buffer uint32_t i ; // Indent counter uint32_t nSize ; // Size of logserver client request uint32_t nProcID ; // Caller process id
va_start(ap1, va_alist) ; va_copy(ap2, ap1) ;
fmt = va_alist ;
// If log channel not open just return if (!IsOpen()) return E_OK ;
if (m_nSessID == 0) { // Log channel is using a direct file
m_Lock.Lock() ;
_logrotate() ;
if (m_bVerbose) { for (i = m_nIndent ; i ; i--) printf("\t") ;
printf("T%uL%d: %04d/%02d/%02d-%02d:%02d:%02d.%06d %s:\t", _hzGlobal_currProc->GetId(), _hzGlobal_currProc->Level(), m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day(), m_datCurr.Hour(), m_datCurr.Min(), m_datCurr.Sec(), m_datCurr.uSec(), _hzGlobal_currProc->GetCurrFunc()) ;
// Print supplied message vprintf(fmt, ap1) ; va_end(ap1) ; fflush(stdout) ; }
if (m_pFile) { for (i = m_nIndent ; i ; i--) fprintf(m_pFile, "\t") ;
fprintf(m_pFile, "T%uL%d: %04d/%02d/%02d-%02d:%02d:%02d.%06d %s:\t", _hzGlobal_currProc->GetId(), _hzGlobal_currProc->Level(), m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day(), m_datCurr.Hour(), m_datCurr.Min(), m_datCurr.Sec(), m_datCurr.uSec(), _hzGlobal_currProc->GetCurrFunc()) ;
// Write supplied message to logfile vfprintf(m_pFile, fmt, ap2) ; va_end(ap2) ; fflush(m_pFile) ; }
m_Lock.Unlock() ; return E_OK ; }
// Log channel is using the logserver
u = (uchar*) m_cvData ; vsprintf(m_cvData + 10, fmt, ap1) ;
nSize = 11 + strlen(m_cvData + 10) ; nProcID = getpid() ;
// Command u[0] = LS_LOG ;
// Size of message u[1] = (nSize & 0xff00) >> 8 ; u[2] = (nSize & 0xff) ;
// Session ID is 0 in this case u[3] = (m_nSessID & 0xff0000) >> 16 ; u[4] = (m_nSessID & 0xff00) >> 8 ; u[5] = (m_nSessID & 0xff) ;
// Process ID u[6] = (nProcID & 0xff00) >> 24 ; u[7] = (nProcID & 0xff00) >> 16 ; u[8] = (nProcID & 0xff00) >> 8 ; u[9] = (nProcID & 0xff) ;
// Send message
if (m_pConnection->Send(m_cvData, nSize) != E_OK) return E_SENDFAIL ;
if (m_pConnection->Recv(m_cvData, nSize, 64) != E_OK) return E_RECVFAIL ;
if (m_cvData[0] == LS_OK) return E_OK ; return E_PROTOCOL ; }
hzEcode hzLogger::Log (const hzChain& Z) { // Writes out the supplied chain to the logfile 'as is' with no time-stamp or other supporting information. // // Arguments: 1) Z Chain to output to logfile // // Returns: E_SENDFAIL If logging is to the logserver and could not be sent // E_RECVFAIL If logging is to the logserver and acknowledgemnt was not recieved // E_PROTOCOL If logging is to the logserver and said logserver did not observe protocol // E_OK If the log action was completed
hzChain::Iter zi ; // Message chain iterator
char* i ; // For population of buffer int32_t n ; // Indent counter uint32_t nBytes ; // Number of bytes in buffer hzEcode rc = E_OK ; // Return code
// m_Temp.Clear() ;
if (Z.Size()) { m_Lock.Lock() ;
_logrotate() ;
if (m_bVerbose) { for (n = m_nIndent ; n ; n--) printf("\t") ;
printf("T%uL%d: %04d/%02d/%02d-%02d:%02d:%02d.%06d %s:\t", _hzGlobal_currProc->GetId(), _hzGlobal_currProc->Level(), m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day(), m_datCurr.Hour(), m_datCurr.Min(), m_datCurr.Sec(), m_datCurr.uSec(), _hzGlobal_currProc->GetCurrFunc()) ;
std::cout << Z ; }
// Write to file for (n = m_nIndent ; n ; n--) fprintf(m_pFile, "\t") ;
fprintf(m_pFile, "T%uL%d: %04d/%02d/%02d-%02d:%02d:%02d.%06d %s:\t", _hzGlobal_currProc->GetId(), _hzGlobal_currProc->Level(), m_datCurr.Year(), m_datCurr.Month(), m_datCurr.Day(), m_datCurr.Hour(), m_datCurr.Min(), m_datCurr.Sec(), m_datCurr.uSec(), _hzGlobal_currProc->GetCurrFunc()) ;
for (zi = Z ; rc == E_OK && !zi.eof() ;) { for (i = m_pDataPtr, nBytes = 0 ; !zi.eof() && nBytes < HZ_LOGCHUNK ; nBytes++, zi++) *i++ = *zi ;
if (!nBytes) break ;
m_pDataPtr[nBytes] = 0 ; rc = _write(nBytes) ; }
m_Lock.Unlock() ; }
return rc ; }
hzEcode hzLogger::Out (const hzChain& Z) { // Writes out the supplied chain to the logfile 'as is' with no time-stamp or other supporting information. // // Arguments: 1) Z Chain to output to logfile // // Returns: E_SENDFAIL If logging is to the logserver and could not be sent // E_RECVFAIL If logging is to the logserver and acknowledgemnt was not recieved // E_PROTOCOL If logging is to the logserver and said logserver did not observe protocol // E_OK If the log action was completed
//_hzfunc("hzLogger::Out(hzChain)") ;
hzChain::Iter zi ; // Message chain iterator
char* i ; // For population of buffer uint32_t nBytes ; // Number of bytes in buffer hzEcode rc = E_OK ; // Return code
if (!_hzGlobal_currProc) { printf("Fatal - no current process\n") ; exit(-1) ; }
if (Z.Size()) { m_Lock.Lock() ;
_logrotate() ;
if (m_bVerbose) std::cout << Z ;
if (m_pFile) { for (zi = Z ; rc == E_OK && !zi.eof() ;) { for (i = m_pDataPtr, nBytes = 0 ; !zi.eof() && nBytes < HZ_LOGCHUNK ; nBytes++, zi++) *i++ = *zi ;
if (!nBytes) break ;
m_pDataPtr[nBytes] = 0 ; rc = _write(nBytes) ; } }
m_Lock.Unlock() ; }
return rc ; }
hzEcode hzLogger::Out (const char* va_alist ...) { // Writes out the supplied character string with varags to the logfile 'as is' with no time-stamp or other supporting information. // // Arguments: 1) va_alist Variable argument format string // // Returns: E_SENDFAIL If logging is to the logserver and could not be sent // E_RECVFAIL If logging is to the logserver and acknowledgemnt was not recieved // E_PROTOCOL If logging is to the logserver and said logserver did not observe protocol // E_OK If the log action was completed
//_hzfunc("hzLogger::Out(...)") ;
va_list ap1 ; // Variable arguments list va_list ap2 ; // Copy of variable arguments list const char* fmt ; // Format control string uchar* u ; // Pointer into message buffer uint32_t i ; // Indent counter uint32_t nSize ; // Size of logserver client request uint32_t nProcID ; // Caller process id
va_start(ap1, va_alist) ; va_copy(ap2, ap1) ;
fmt = va_alist ;
// m_Temp.Clear() ;
// If log channel not open just return
if (!IsOpen()) return E_OK ;
// If log channel is using a direct file
if (m_nSessID == 0) { m_Lock.Lock() ; _logrotate() ;
if (m_bVerbose) { for (i = m_nIndent ; i ; i--) printf("\t") ;
vprintf(fmt, ap1) ; va_end(ap1) ; fflush(stdout) ; }
if (m_pFile) { for (i = m_nIndent ; i ; i--) fprintf(m_pFile, "\t") ;
vfprintf(m_pFile, fmt, ap2) ; va_end(ap2) ; fflush(m_pFile) ; }
m_Lock.Unlock() ; return E_OK ; }
// Log channel is using the logserver
u = (uchar*) m_cvData ; vsprintf(m_cvData + 10, fmt, ap1) ;
nSize = 11 + strlen(m_cvData + 10) ; nProcID = getpid() ;
// Command u[0] = LS_LOG ;
// Size of message u[1] = (nSize & 0xff00) >> 8 ; u[2] = (nSize & 0xff) ;
// Session ID is 0 in this case u[3] = (m_nSessID & 0xff0000) >> 16 ; u[4] = (m_nSessID & 0xff00) >> 8 ; u[5] = (m_nSessID & 0xff) ;
// Process ID u[6] = (nProcID & 0xff00) >> 24 ; u[7] = (nProcID & 0xff00) >> 16 ; u[8] = (nProcID & 0xff00) >> 8 ; u[9] = (nProcID & 0xff) ;
// Send message
if (m_pConnection->Send(m_cvData, nSize) != E_OK) return E_SENDFAIL ;
if (m_pConnection->Recv(m_cvData, nSize, 64) != E_OK) return E_RECVFAIL ;
if (m_cvData[0] == LS_OK) return E_OK ; return E_PROTOCOL ; }
hzLogger& hzLogger::operator<< (hzChain& Z) { // Stream operator so that an entire hzChain contents can be output to the logfile. // // Arguments: 1) Z Chain to aggregate to logger // // Returns: Reference to this logger
//_hzfunc("hzLogger::operator<<(hzChain)") ;
hzChain::Iter zi ; // Message chain iterator
char* i ; // For population of buffer uint32_t nBytes ; // Number of bytes in buffer hzEcode rc = E_OK ; // Return code
// m_Temp.Clear() ;
if (Z.Size()) { m_Lock.Lock() ; _logrotate() ;
if (m_bVerbose) { std::cout.write(m_pDataPtr, nBytes) ; fflush(stdout) ; }
zi = Z ; for (; rc == E_OK ;) { for (i = m_pDataPtr, nBytes = 0 ; !zi.eof() && nBytes < HZ_LOGCHUNK ; nBytes++, zi++) *i++ = *zi ;
if (!nBytes) break ;
m_pDataPtr[nBytes] = 0 ; rc = _write(nBytes) ; }
m_Lock.Unlock() ; }
return *this ; }
hzLogger& hzLogger::operator<< (hzString& S) { // Stream operator so that a hzString can be output to the logfile. // // Arguments: 1) S String to aggregate to logger // // Returns: Reference to this logger
//_hzfunc("hzLogger::operator<<(hzString)") ;
const char* i ; // Message as null terminated string char* j ; // Message iterator uint32_t nBytes ; // Size of message hzEcode rc = E_OK ; // Return code
// m_Temp.Clear() ;
if (S.Length()) { m_Lock.Lock() ; _logrotate() ;
i = *S ; for (; rc == E_OK ;) { for (j = m_pDataPtr, nBytes = 0 ; *i && nBytes < HZ_LOGCHUNK ; nBytes++) *j++ = *i++ ;
if (!nBytes) break ;
m_pDataPtr[nBytes] = 0 ; rc = _write(nBytes) ; }
m_Lock.Unlock() ; }
return *this ; }
hzLogger& hzLogger::operator<< (const char* str) { // Stream operator so that a char string can be output to the logfile. // // Arguments: 1) str Char string to aggregate to logger // // Returns: Reference to this logger
//_hzfunc("hzLogger::operator<<(cstr)") ;
const char* i ; // Message as null terminated string char* j ; // Message iterator uint32_t nBytes ; // Size of message hzEcode rc = E_OK ; // Return code
// m_Temp.Clear() ;
if (str && str[0]) { m_Lock.Lock() ; _logrotate() ;
i = str ; for (; rc == E_OK ;) { for (j = m_pDataPtr, nBytes = 0 ; *i && nBytes < HZ_LOGCHUNK ; nBytes++) *j++ = *i++ ;
if (!nBytes) break ;
m_pDataPtr[nBytes] = 0 ; rc = _write(nBytes) ; }
m_Lock.Unlock() ; }
return *this ; }
hzEcode threadLog (const char* va_alist ...) { // Category: Diagnostics // // Write message supplied as a vararg CStr to the defualt log-channel of the current thread. If there is no defualt log-channel open, the message is written to stdout. // // Arguments: 1) va_alist Variable args format string // // Returns: E_SENDFAIL If logging is to the logserver and could not be sent // E_RECVFAIL If logging is to the logserver and acknowledgemnt was not recieved // E_PROTOCOL If logging is to the logserver and said logserver did not observe protocol // E_OK If the log action was completed
//_hzfunc("threadLog(va_alist)") ;
va_list ap ; // Variable argument list hzLogger* plog ; // The calling thread's logfile hzChain errmsg ; // The log message
// Do the varargs va_start(ap, va_alist) ; errmsg._vainto(va_alist, ap) ; va_end(ap) ;
// Obtain the log if available plog = GetThreadLogger() ; if (!plog) { std::cout << errmsg ; fflush(stdout) ; return E_NOINIT ; }
// Do the log return plog->Log(errmsg) ; }
hzEcode threadLog (const hzChain& msg) { // Category: Diagnostics // // Write message supplied as a chain to the defualt log-channel of the current thread. If there is no defualt log-channel open, the message is written to stdout. // // Arguments: 1) msg Output message as chain // // Returns: E_SENDFAIL If logging is to the logserver and could not be sent // E_RECVFAIL If logging is to the logserver and acknowledgemnt was not recieved // E_PROTOCOL If logging is to the logserver and said logserver did not observe protocol // E_OK If the log action was completed
//_hzfunc("threadLog(chain)") ;
hzLogger* plog ; // The calling thread's logfile
plog = GetThreadLogger() ; //phz ? phz->GetLog() : 0 ; if (!plog) { std::cout << msg ; fflush(stdout) ; return E_NOINIT ; }
return plog->Log(msg) ; }
hzEcode threadOut (const char* va_alist ...) { // Category: Diagnostics // // Write message supplied as a vararg CStr to the defualt log-channel of the current thread. If there is no defualt log-channel open, the message is written to stdout. // // Arguments: 1) va_alist Variable args format string // // Returns: E_SENDFAIL If logging is to the logserver and could not be sent // E_RECVFAIL If logging is to the logserver and acknowledgemnt was not recieved // E_PROTOCOL If logging is to the logserver and said logserver did not observe protocol // E_OK If the log action was completed
//_hzfunc("threadLog(va_alist)") ;
va_list ap ; // Variable argument list hzLogger* plog ; // The calling thread's logfile hzChain errmsg ; // The log message
// Do the varargs va_start(ap, va_alist) ; errmsg._vainto(va_alist, ap) ; va_end(ap) ;
// Obtain the log if available plog = GetThreadLogger() ; if (!plog) { std::cout << errmsg ; fflush(stdout) ; return E_NOINIT ; }
// Do the log return plog->Out(errmsg) ; }
hzEcode threadOut (const hzChain& msg) { // Category: Diagnostics // // Write message supplied as a chain to the defualt log-channel of the current thread. If there is no defualt log-channel open, the message is written to stdout. // // Arguments: 1) msg Output message as chain // // Returns: E_SENDFAIL If logging is to the logserver and could not be sent // E_RECVFAIL If logging is to the logserver and acknowledgemnt was not recieved // E_PROTOCOL If logging is to the logserver and said logserver did not observe protocol // E_OK If the log action was completed
//_hzfunc("threadLog(chain)") ;
hzLogger* plog ; // The calling thread's logfile
plog = GetThreadLogger() ; //phz ? phz->GetLog() : 0 ; if (!plog) { std::cout << msg ; fflush(stdout) ; return E_NOINIT ; }
return plog->Out(msg) ; }