67void Snatch(
struct iovec *
iov,
int iovnum)
75 if (iovnum && *((
char *)
iov[iovnum-1].iov_base) ==
'\n') iovnum--;
79 for (
int i = 0; i <iovnum; i++) tLen +=
iov[i].iov_len;
83 if (!(tBuff = (
char *)malloc(tLen+1)))
return;
88 for (
int i = 0; i <iovnum; i++)
89 {strncpy(tbP, (
char *)
iov[i].iov_base,
iov[i].iov_len);
90 tbP +=
iov[i].iov_len;
106#define BLAB(x) std::cerr <<"Logger " <<x <<"!!!" <<std::endl
108bool XrdSysLogger::doForward =
false;
116 while(tP) {tP->
Ring(); tP = tP->
Next();}
149 doLFR = (dorotate != 0);
159 if (!(logFN = getenv(
"XrdSysLOGFILE"))) logFN = getenv(
"XrdOucLOGFILE");
163 if (ErrFD != STDERR_FILENO) baseFD = ErrFD;
164 else {baseFD = ErrFD;
166 {baseFD = XrdSysFD_Dup(ErrFD);
178 mmMsg *tP, *nP =
new mmMsg;
183 nP->msg = strdup(msg);
184 nP->mlen = strlen(msg);
188 if (nP->mlen > 1 && nP->msg[nP->mlen-1] !=
'\n')
189 {nP->msg[nP->mlen] =
'\n'; nP->mlen += 1;}
194 if (!(tP = msgList)) msgList = nP;
195 else {
while(tP->next) tP = tP->next;
198 Logger_Mutex.UnLock();
211 mnTask->next = taskQ;
213 Logger_Mutex.UnLock();
227 if (lfh > 0) lfh = 1;
228 if (lfhTID && (eInt != lfh || !path))
235 if (ePath) free(ePath);
238 if (fifoFN) free(fifoFN);
239 fifoFN = 0; doLFR =
false;
245 ePath = strdup(path);
247 if ((rc = ReBind(0)))
return rc;
251 rc = HandleLogRotateLock( doLFR );
257 if (eInt ==
onFifo) {
if ((rc = FifoMake()))
return -rc;}
260 BLAB(
"Unable to block logfile signal " <<-eInt <<
"; "
271 return (rc > 0 ? -rc : rc);
291 Logger_Mutex.UnLock();
306 {
if (!strcmp(arg,
"fifo"))
return onFifo;
312 eKeep = strtoll(arg, &eP, 10);
313 if (!(*eP) || eKeep < 0) {eKeep = -eKeep;
return 1;}
317 if (*(eP+1))
return 0;
318 if (*eP ==
'k' || *eP ==
'K') eKeep *= 1024LL;
319 else if (*eP ==
'm' || *eP ==
'M') eKeep *= 1024LL*1024LL;
320 else if (*eP ==
'g' || *eP ==
'G') eKeep *= 1024LL*1024LL*1024LL;
321 else if (*eP ==
't' || *eP ==
'T') eKeep *= 1024LL*1024LL*1024LL*1024LL;
342 gettimeofday(&tVal, 0);
355 if (!
iov[0].iov_base)
356 {
iov[0].iov_base = tbuff;
357 iov[0].iov_len = TimeStamp(tVal, tID, tbuff,
sizeof(tbuff), hiRes);
367 {Snatch(
iov, iovcnt);
368 Logger_Mutex.UnLock();
375 do { retc =
writev(eFD, (
const struct iovec *)
iov, iovcnt);}
376 while (retc < 0 && errno == EINTR);
380 Logger_Mutex.UnLock();
387int XrdSysLogger::Time(
char *tbuff)
390 const int minblen = 32;
396 gettimeofday(&tVal, 0);
400 localtime_r((
const time_t *) &tVal.tv_sec, &tNow);
405 {i = snprintf(tbuff, minblen,
"%02d%02d%02d %02d:%02d:%02d.%06d %03ld ",
406 tNow.tm_year-100, tNow.tm_mon+1, tNow.tm_mday,
407 tNow.tm_hour, tNow.tm_min, tNow.tm_sec,
410 i = snprintf(tbuff, minblen,
"%02d%02d%02d %02d:%02d:%02d %03ld ",
411 tNow.tm_year-100, tNow.tm_mon+1, tNow.tm_mday,
412 tNow.tm_hour, tNow.tm_min, tNow.tm_sec,
415 return (i >= minblen ? minblen-1 : i);
422int XrdSysLogger::TimeStamp(
struct timeval &tVal,
unsigned long tID,
423 char *tbuff,
int tbsz,
bool hires)
430 if (tbsz <= 0)
return 0;
434 localtime_r((
const time_t *) &tVal.tv_sec, &tNow);
439 {i = snprintf(tbuff, tbsz,
"%02d%02d%02d %02d:%02d:%02d.%06d %03ld ",
440 tNow.tm_year-100, tNow.tm_mon+1, tNow.tm_mday,
441 tNow.tm_hour, tNow.tm_min, tNow.tm_sec,
442 static_cast<int>(tVal.tv_usec), tID);
444 i = snprintf(tbuff, tbsz,
"%02d%02d%02d %02d:%02d:%02d %03ld ",
445 tNow.tm_year-100, tNow.tm_mon+1, tNow.tm_mday,
446 tNow.tm_hour, tNow.tm_min, tNow.tm_sec, tID);
448 return (i >= tbsz ? tbsz-1 : i);
458int XrdSysLogger::FifoMake()
461 char buff[2048], *slash;
462 int n, rc, saveInt = eInt;
470 if (!(slash = rindex(ePath,
'/')))
472 strcpy(buff+1, ePath);
474 n = slash - ePath + 1;
475 strncpy(buff, ePath, n);
477 strcpy(&buff[n+1], slash+1);
483 {
if (!S_ISFIFO(
Stat.st_mode))
484 {
BLAB(
"Logfile fifo " <<buff <<
" exists but is not a fifo");
487 else if (
access(buff, R_OK))
488 {
BLAB(
"Unable to access " <<buff);
497 BLAB(buff <<
" has been removed");
512 {
if (mkfifo(buff, S_IRUSR|S_IWUSR))
514 BLAB(
"Unable to create logfile fifo " <<buff <<
"; " <<
XrdSysE2T(rc));
521 fifoFN = strdup(buff);
529int XrdSysLogger::HandleLogRotateLock(
bool dorotate )
531 if( !ePath )
return 0;
533 char *end = rindex(ePath,
'/');
534 const std::string lckPath = (end ? std::string(ePath,end+1)+
".lock" :
".lock");
535 int rc =
unlink( lckPath.c_str() );
536 if( rc && errno != ENOENT )
538 BLAB(
"The logfile lock (" << lckPath.c_str() <<
") exists and cannot be removed: " <<
XrdSysE2T( errno ) );
544 rc =
open( lckPath.c_str(), O_CREAT, 0644 );
547 BLAB(
"Failed to create the logfile lock (" << lckPath.c_str() <<
"): " <<
XrdSysE2T( errno ) );
559void XrdSysLogger::RmLogRotateLock()
563 char *end = rindex(ePath,
'/') + 1;
564 const std::string lckPath = std::string( ePath, end ) +
".lock";
565 unlink( lckPath.c_str() );
572void XrdSysLogger::FifoWait()
580 if ((pipeFD = XrdSysFD_Open(fifoFN, O_RDONLY)) < 0)
582 BLAB(
"Unable to open logfile fifo " <<fifoFN <<
"; " <<
XrdSysE2T(rc));
584 free(fifoFN); fifoFN = 0;
590 if (!
read(pipeFD, buff,
sizeof(buff)))
591 {
BLAB(
"Unexpected EOF on logfile fifo " <<fifoFN);
603void XrdSysLogger::putEmsg(
char *msg,
int msz)
608 struct iovec eVec[2] = {{tbuff, 0}, {msg, (size_t)msz}};
613 gettimeofday(&tVal, 0);
621 eVec[0].iov_len = TimeStamp(tVal, tID, tbuff,
sizeof(tbuff), hiRes);
626 do { retc =
writev(eFD, (
const struct iovec *)eVec, 2);}
627 while (retc < 0 && errno == EINTR);
634int XrdSysLogger::ReBind(
int dorename)
636 const char seq[] =
"0123456789";
640 char *bp, buff[MAXPATHLEN+MAXNAMELEN];
646 if (dorename && doLFR)
647 {strcpy(buff, ePath);
648 bp = buff+strlen(ePath);
650 strncpy(bp, Filesfx, 8);
652 *bp =
'\0'; *(bp+2) =
'\0';
653 for (i = 0; i <
sizeof(seq) && !
stat(buff, &bf); i++)
654 {*bp =
'.'; *(bp+1) = (
char)seq[i];}
655 if (i <
sizeof(seq))
rename(ePath, buff);
661 {time_t eNow = time(0);
662 localtime_r((
const time_t *) &eNow, &nowtime);
663 sprintf(buff,
"%4d%02d%02d", nowtime.tm_year+1900, nowtime.tm_mon+1,
665 memcpy(Filesfx, buff, 8);
671 if ((newfd = XrdSysFD_Open(ePath,O_WRONLY|O_APPEND|O_CREAT,0644)) < 0)
677 if (dup2(newfd, eFD) < 0)
686 if (eKeep && doLFR) Trim();
695void XrdSysLogger::Trim()
703 LogFile(
char *xfn, off_t xsz, time_t xtm)
704 {fn = (xfn ? strdup(xfn) : 0); sz = xsz; tm = xtm; next = 0;}
707 if (next)
delete next;
711 struct LogFile *logEnt, *logPrev, *logNow;
712 char eBuff[2048], logFN[MAXNAMELEN+8], logDir[MAXPATHLEN+8], *logSfx;
726 strcpy(logDir, ePath);
727 if (!(logSfx = rindex(logDir,
'/')))
return;
729 strcpy(logFN, logSfx+1);
735 {
int msz = snprintf(eBuff, 2048,
"Error %d (%s) opening log directory %s\n",
746 {
if (strncmp(dp->d_name, logFN, n))
continue;
747 strcpy(logSfx, dp->d_name);
748 if (
stat(logDir, &buff) || !(buff.st_mode & S_IFREG))
continue;
750 totNum++; totSz += buff.st_size;
751 logEnt =
new LogFile(dp->d_name, buff.st_size, buff.st_mtime);
752 logPrev = &logList; logNow = logList.next;
753 while(logNow && logNow->tm < buff.st_mtime)
754 {logPrev = logNow; logNow = logNow->next;}
756 logPrev->next = logEnt;
757 logEnt->next = logNow;
764 {
int msz = snprintf(eBuff, 2048,
"Error %d (%s) reading log directory %s\n",
772 if (totNum <= 1)
return;
777 {
if ((totNum += eKeep) <= 0)
return;
779 if (totSz <= eKeep)
return;
780 logNow = logList.next; totNum = 0;
781 while(logNow && totSz > eKeep)
782 {totNum++; totSz -= logNow->sz; logNow = logNow->next;}
787 logNow = logList.next;
788 while(logNow && totNum--)
789 {strcpy(logSfx, logNow->fn);
791 rc = snprintf(eBuff, 2048,
"Error %d (%s) removing log file %s\n",
793 else rc = snprintf(eBuff, 2048,
"Removed log file %s\n", logDir);
795 logNow = logNow->next;
799void XrdSysLogger::Trim()
819 if (eInt < 0 && !fifoFN)
821 if ((sigemptyset(&sigset) == -1)
822 || (sigaddset(&sigset,signo) == -1))
824 BLAB(
"Unable to use logfile signal " <<signo <<
"; " <<
XrdSysE2T(rc));
832 {
if (fifoFN) FifoWait();
834 else if ((sigwait(&sigset, &signo) == -1))
836 BLAB(
"Unable to wait on logfile signal " <<signo
847 {putEmsg(mP->msg, mP->mlen);
851 Logger_Mutex.UnLock();
855 "Midnight Ringer Task"))
857 rc = sprintf(eBuff,
"Error %d (%s) running ringer task.\n",
const char * XrdSysE2T(int errcode)
void * XrdSysLoggerRT(void *carg)
void * XrdSysLoggerMN(void *carg)
void Add(XrdOucTList *tP)
virtual void Ring()=0
This method gets called at midnight.
void Put(int iovcnt, struct iovec *iov)
void AddMsg(const char *msg)
XrdSysLogger(int ErrFD=STDERR_FILENO, int xrotate=1)
void AtMidnight(Task *mnTask)
void Capture(XrdOucTListFIFO *tFIFO)
int Bind(const char *path, int lfh=0)
int ParseKeep(const char *arg)
static bool Forward(struct timeval mtime, unsigned long tID, struct iovec *iov, int iovcnt)
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
static int Kill(pthread_t tid)
static unsigned long Num(void)
static void Wait4Midnight()
static int GetSigNum(const char *sname)
XrdSysLoggerRP(XrdSysLogger *lp)