XRootD
Loading...
Searching...
No Matches
XrdSysLogger.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d S y s L o g g e r . c c */
4/* */
5/*(c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
6/*Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Deprtment of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <fcntl.h>
31#include <signal.h>
32#include <cstdlib>
33#include <cstdio>
34#include <cstring>
35#include <ctime>
36#include <sys/stat.h>
37#include <sys/types.h>
38#ifndef WIN32
39#include <dirent.h>
40#include <unistd.h>
41#include <strings.h>
42#include <sys/param.h>
43#include <termios.h>
44#include <sys/uio.h>
45#endif // WIN32
46
47#include "XrdOuc/XrdOucTList.hh"
48
49#include "XrdSys/XrdSysE2T.hh"
50#include "XrdSys/XrdSysFD.hh"
56#include "XrdSys/XrdSysTimer.hh"
57#include "XrdSys/XrdSysUtils.hh"
58
59/******************************************************************************/
60/* G l o b a l s */
61/******************************************************************************/
62
63namespace
64{
65XrdOucTListFIFO *tFifo = 0;
66
67void Snatch(struct iovec *iov, int iovnum) // Called with logger mutex locked!
68{
69 XrdOucTList *tlP;
70 char *tBuff, *tbP;
71 int tLen = 0;
72
73// Do not save the new line character at the end
74//
75 if (iovnum && *((char *)iov[iovnum-1].iov_base) == '\n') iovnum--;
76
77// Calculate full length
78//
79 for (int i = 0; i <iovnum; i++) tLen += iov[i].iov_len;
80
81// Allocate storage
82//
83 if (!(tBuff = (char *)malloc(tLen+1))) return;
84
85// Copy in the segments into the buffer
86//
87 tbP = tBuff;
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;
91 }
92 *tbP = 0;
93
94// Allocate a new tlist object and add it toi the fifo
95//
96 tlP = new XrdOucTList;
97 tlP->text = tBuff;
98 tFifo->Add(tlP);
99}
100}
101
102/******************************************************************************/
103/* L o c a l D e f i n e s */
104/******************************************************************************/
105
106#define BLAB(x) std::cerr <<"Logger " <<x <<"!!!" <<std::endl
107
108bool XrdSysLogger::doForward = false;
109
110/******************************************************************************/
111/* E x t e r n a l T h r e a d I n t e r f a c e s */
112/******************************************************************************/
113
114void *XrdSysLoggerMN(void *carg)
116 while(tP) {tP->Ring(); tP = tP->Next();}
117 return (void *)0;
118 }
119
128
129void *XrdSysLoggerRT(void *carg)
130 {XrdSysLoggerRP *rP = (XrdSysLoggerRP *)carg;
131 XrdSysLogger *lp = rP->logger;
132 rP->active.Post();
133 lp->zHandler();
134 return (void *)0;
135 }
136
137/******************************************************************************/
138/* C o n s t r u c t o r */
139/******************************************************************************/
140
141XrdSysLogger::XrdSysLogger(int ErrFD, int dorotate)
142{
143 char * logFN;
144
145 ePath = 0;
146 eInt = 0;
147 eFD = ErrFD;
148 eKeep = 0;
149 doLFR = (dorotate != 0);
150 msgList = 0;
151 taskQ = 0;
152 lfhTID = 0;
153 hiRes = false;
154 fifoFN = 0;
155 reserved1 = 0;
156
157// Establish default log file name
158//
159 if (!(logFN = getenv("XrdSysLOGFILE"))) logFN = getenv("XrdOucLOGFILE");
160
161// Establish message routing
162//
163 if (ErrFD != STDERR_FILENO) baseFD = ErrFD;
164 else {baseFD = ErrFD;
165 if (logFN)
166 {baseFD = XrdSysFD_Dup(ErrFD);
167 Bind(logFN, 1);
168 }
169 }
170}
171
172/******************************************************************************/
173/* A d d M s g */
174/******************************************************************************/
175
176void XrdSysLogger::AddMsg(const char *msg)
177{
178 mmMsg *tP, *nP = new mmMsg;
179
180// Fill out new message
181//
182 nP->next = 0;
183 nP->msg = strdup(msg);
184 nP->mlen = strlen(msg);
185
186// Add new line character if one is missing (we steal the null byte for this)
187//
188 if (nP->mlen > 1 && nP->msg[nP->mlen-1] != '\n')
189 {nP->msg[nP->mlen] = '\n'; nP->mlen += 1;}
190
191// Add this message to the end of the list
192//
193 Logger_Mutex.Lock();
194 if (!(tP = msgList)) msgList = nP;
195 else {while(tP->next) tP = tP->next;
196 tP->next = nP;
197 }
198 Logger_Mutex.UnLock();
199}
200
201/******************************************************************************/
202/* A t M i d n i g h t */
203/******************************************************************************/
204
206{
207
208// Place this task on the task queue
209//
210 Logger_Mutex.Lock();
211 mnTask->next = taskQ;
212 taskQ = mnTask;
213 Logger_Mutex.UnLock();
214}
215
216/******************************************************************************/
217/* B i n d */
218/******************************************************************************/
219
220int XrdSysLogger::Bind(const char *path, int lfh)
221{
222 XrdSysLoggerRP rtParms(this);
223 int rc;
224
225// Kill logfile handler thread if parameters will be changing
226//
227 if (lfh > 0) lfh = 1;
228 if (lfhTID && (eInt != lfh || !path))
229 {XrdSysThread::Kill(lfhTID);
230 lfhTID = 0;
231 }
232
233// Bind to stderr if no path specified
234//
235 if (ePath) free(ePath);
236 eInt = 0;
237 ePath = 0;
238 if (fifoFN) free(fifoFN);
239 fifoFN = 0; doLFR = false;
240 if (!path) return 0;
241
242// Bind to a log file
243//
244 eInt = lfh;
245 ePath = strdup(path);
246 doLFR = (lfh > 0);
247 if ((rc = ReBind(0))) return rc;
248
249// Lock the logs if XRootD is suppose to handle log rotation itself
250//
251 rc = HandleLogRotateLock( doLFR );
252 if( rc )
253 return -rc;
254
255// Handle specifics of lofile rotation
256//
257 if (eInt == onFifo) {if ((rc = FifoMake())) return -rc;}
258 else if (eInt < 0 && !XrdSysUtils::SigBlock(-eInt))
259 {rc = errno;
260 BLAB("Unable to block logfile signal " <<-eInt <<"; "
261 <<XrdSysE2T(rc));
262 eInt = 0;
263 return -rc;
264 }
265
266// Start a log rotation thread
267//
268 rc = XrdSysThread::Run(&lfhTID, XrdSysLoggerRT, (void *)&rtParms, 0,
269 "Logfile handler");
270 if (!rc) rtParms.active.Wait();
271 return (rc > 0 ? -rc : rc);
272}
273
274/******************************************************************************/
275/* C a p t u r e */
276/******************************************************************************/
277
279{
280
281// Obtain the serailization mutex
282//
283 Logger_Mutex.Lock();
284
285// Set the base for capturing messages
286//
287 tFifo = tFIFO;
288
289// Release the serailization mutex
290//
291 Logger_Mutex.UnLock();
292}
293
294/******************************************************************************/
295/* P a r s e K e e p */
296/******************************************************************************/
297
298int XrdSysLogger::ParseKeep(const char *arg)
299{
300 char *eP;
301
302// First check to see if this is a sig type
303//
304 eKeep = 0;
305 if (isalpha(*arg))
306 {if (!strcmp(arg, "fifo")) return onFifo;
307 return -XrdSysUtils::GetSigNum(arg);
308 }
309
310// Process an actual keep count
311//
312 eKeep = strtoll(arg, &eP, 10);
313 if (!(*eP) || eKeep < 0) {eKeep = -eKeep; return 1;}
314
315// Process an actual keep size
316//
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;
322 else return 0;
323
324// All done
325//
326 return 1;
327}
328
329/******************************************************************************/
330/* P u t */
331/******************************************************************************/
332
333void XrdSysLogger::Put(int iovcnt, struct iovec *iov)
334{
335 struct timeval tVal;
336 unsigned long tID = XrdSysThread::Num();
337 int retc;
338 char tbuff[32];
339
340// Get current time
341//
342 gettimeofday(&tVal, 0);
343
344// Forward the message if there is a plugin involved here
345//
346 if (doForward)
347 {bool xEnd;
348 if (iov[0].iov_base) xEnd = XrdSysLogging::Forward(tVal,tID,iov,iovcnt);
349 else xEnd = XrdSysLogging::Forward(tVal, tID, &iov[1], iovcnt-1);
350 if (xEnd) return;
351 }
352
353// Prefix message with time if calle wants it so
354//
355 if (!iov[0].iov_base)
356 {iov[0].iov_base = tbuff;
357 iov[0].iov_len = TimeStamp(tVal, tID, tbuff, sizeof(tbuff), hiRes);
358 }
359
360// Obtain the serailization mutex if need be
361//
362 Logger_Mutex.Lock();
363
364// If we are capturing messages, do so now
365//
366 if (tFifo)
367 {Snatch(iov, iovcnt);
368 Logger_Mutex.UnLock();
369 return;
370 }
371
372// In theory, writev may write out a partial list. This rarely happens in
373// practice and so we ignore that possibility (recovery is pretty tough).
374//
375 do { retc = writev(eFD, (const struct iovec *)iov, iovcnt);}
376 while (retc < 0 && errno == EINTR);
377
378// Release the serailization mutex if need be
379//
380 Logger_Mutex.UnLock();
381}
382
383/******************************************************************************/
384/* Private: T i m e */
385/******************************************************************************/
386
387int XrdSysLogger::Time(char *tbuff)
388{
389 struct timeval tVal;
390 const int minblen = 32;
391 struct tm tNow;
392 int i;
393
394// Get the current time
395//
396 gettimeofday(&tVal, 0);
397
398// Format the time in human terms
399//
400 localtime_r((const time_t *) &tVal.tv_sec, &tNow);
401
402// Choose appropriate output
403//
404 if (hiRes)
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,
408 static_cast<int>(tVal.tv_usec), XrdSysThread::Num());
409 } else {
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,
414 }
415 return (i >= minblen ? minblen-1 : i);
416}
417
418/******************************************************************************/
419/* Private: T i m e S t a m p */
420/******************************************************************************/
421
422int XrdSysLogger::TimeStamp(struct timeval &tVal, unsigned long tID,
423 char *tbuff, int tbsz, bool hires)
424{
425 struct tm tNow;
426 int i;
427
428// Validate tbuff size
429//
430 if (tbsz <= 0) return 0;
431
432// Format the time in human terms
433//
434 localtime_r((const time_t *) &tVal.tv_sec, &tNow);
435
436// Choose appropriate output
437//
438 if (hires)
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);
443 } else {
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);
447 }
448 return (i >= tbsz ? tbsz-1 : i);
449}
450
451/******************************************************************************/
452/* P r i v a t e M e t h o d s */
453/******************************************************************************/
454/******************************************************************************/
455/* F i f o M a k e */
456/******************************************************************************/
457
458int XrdSysLogger::FifoMake()
459{
460 struct stat Stat;
461 char buff[2048], *slash;
462 int n, rc, saveInt = eInt;
463
464// Assume failure (just to keep down the code)
465//
466 eInt = 0;
467
468// Construct the fifo name
469//
470 if (!(slash = rindex(ePath, '/')))
471 {*buff = '.';
472 strcpy(buff+1, ePath);
473 } else {
474 n = slash - ePath + 1;
475 strncpy(buff, ePath, n);
476 buff[n] = '.';
477 strcpy(&buff[n+1], slash+1);
478 }
479
480// Check if the fifo exists and is usable or that we can create it
481//
482 if (!stat(buff, &Stat))
483 { if (!S_ISFIFO(Stat.st_mode))
484 {BLAB("Logfile fifo " <<buff <<" exists but is not a fifo");
485 rc = EEXIST;
486 }
487 else if (access(buff, R_OK))
488 {BLAB("Unable to access " <<buff);
489 rc = EACCES;
490 }
491 else rc = 0;
492 if (rc)
493 {if (unlink(buff))
494 {BLAB("Unable to remove " <<buff <<"; " <<XrdSysE2T(errno));
495 return rc;
496 } else {
497 BLAB(buff <<" has been removed");
498 rc = ENOENT;
499 }
500 }
501 } else {
502 rc = errno;
503 if (rc != ENOENT)
504 {BLAB("Unable to stat " <<buff <<"; " <<XrdSysE2T(rc));
505 return rc;
506 }
507 }
508
509// Now try to create the fifo if we actually need to
510//
511 if (rc == ENOENT)
512 {if (mkfifo(buff, S_IRUSR|S_IWUSR))
513 {rc = errno;
514 BLAB("Unable to create logfile fifo " <<buff <<"; " <<XrdSysE2T(rc));
515 return rc;
516 }
517 }
518
519// Save the fifo path restore eInt
520//
521 fifoFN = strdup(buff);
522 eInt = saveInt;
523 return 0;
524}
525
526/******************************************************************************/
527/* H a n d l e L o g R o t a t e L o c k */
528/******************************************************************************/
529int XrdSysLogger::HandleLogRotateLock( bool dorotate )
530{
531 if( !ePath ) return 0;
532
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 )
537 {
538 BLAB( "The logfile lock (" << lckPath.c_str() << ") exists and cannot be removed: " << XrdSysE2T( errno ) );
539 return EEXIST;
540 }
541
542 if( dorotate )
543 {
544 rc = open( lckPath.c_str(), O_CREAT, 0644 );
545 if( rc < 0 )
546 {
547 BLAB( "Failed to create the logfile lock (" << lckPath.c_str() << "): " << XrdSysE2T( errno ) );
548 return errno;
549 }
550 close( rc );
551 }
552
553 return 0;
554}
555
556/******************************************************************************/
557/* R m L o g R o t a t e L o c k */
558/******************************************************************************/
559void XrdSysLogger::RmLogRotateLock()
560{
561 if( !ePath ) return;
562
563 char *end = rindex(ePath, '/') + 1;
564 const std::string lckPath = std::string( ePath, end ) + ".lock";
565 unlink( lckPath.c_str() );
566}
567
568/******************************************************************************/
569/* F i f o W a i t */
570/******************************************************************************/
571
572void XrdSysLogger::FifoWait()
573{
574 char buff[64];
575 int pipeFD, rc;
576
577// Open the fifo. We can't have this block as we need to make sure it is
578// closed on EXEC as fast as possible (Linux has a non-portable solution).
579//
580 if ((pipeFD = XrdSysFD_Open(fifoFN, O_RDONLY)) < 0)
581 {rc = errno;
582 BLAB("Unable to open logfile fifo " <<fifoFN <<"; " <<XrdSysE2T(rc));
583 eInt = 0;
584 free(fifoFN); fifoFN = 0;
585 return;
586 }
587
588// Wait for read, this will block. If we got an EOF then something went wrong!
589//
590 if (!read(pipeFD, buff, sizeof(buff)))
591 {BLAB("Unexpected EOF on logfile fifo " <<fifoFN);
592 eInt = 0;
593 }
594 close(pipeFD);
595}
596
597/******************************************************************************/
598/* p u t E m s g */
599/******************************************************************************/
600
601// This internal logging method is used when the caller already has the mutex!
602
603void XrdSysLogger::putEmsg(char *msg, int msz)
604{
605 unsigned long tID = XrdSysThread::Num();
606 char tbuff[32];
607 struct timeval tVal;
608 struct iovec eVec[2] = {{tbuff, 0}, {msg, (size_t)msz}};
609 int retc;
610
611// Get current time
612//
613 gettimeofday(&tVal, 0);
614
615// Forward the message if there is a plugin involved here
616//
617 if (doForward && XrdSysLogging::Forward(tVal, tID, &eVec[1], 1)) return;
618
619// Prefix message with time
620//
621 eVec[0].iov_len = TimeStamp(tVal, tID, tbuff, sizeof(tbuff), hiRes);
622
623// In theory, writev may write out a partial list. This rarely happens in
624// practice and so we ignore that possibility (recovery is pretty tough).
625//
626 do { retc = writev(eFD, (const struct iovec *)eVec, 2);}
627 while (retc < 0 && errno == EINTR);
628}
629
630/******************************************************************************/
631/* R e B i n d */
632/******************************************************************************/
633
634int XrdSysLogger::ReBind(int dorename)
635{
636 const char seq[] = "0123456789";
637 unsigned int i;
638 int newfd;
639 struct tm nowtime;
640 char *bp, buff[MAXPATHLEN+MAXNAMELEN];
641 struct stat bf;
642
643// Rename the file to be of the form yyyymmdd corresponding to the date it was
644// opened. We will add a sequence number (.x) if a conflict occurs.
645//
646 if (dorename && doLFR)
647 {strcpy(buff, ePath);
648 bp = buff+strlen(ePath);
649 *bp++ = '.';
650 strncpy(bp, Filesfx, 8);
651 bp += 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);
656 }
657
658// Compute the suffix for the file
659//
660 if (doLFR)
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,
664 nowtime.tm_mday);
665 memcpy(Filesfx, buff, 8);
666 }
667
668// Open the file for output. Note that we can still leak a file descriptor
669// if a thread forks a process before we are able to do the fcntl(), sigh.
670//
671 if ((newfd = XrdSysFD_Open(ePath,O_WRONLY|O_APPEND|O_CREAT,0644)) < 0)
672 return -errno;
673
674// Now set the file descriptor to be the same as the error FD. This will
675// close the previously opened file, if any.
676//
677 if (dup2(newfd, eFD) < 0)
678 {int rc = errno;
679 close(newfd);
680 return -rc;
681 }
682 close(newfd);
683
684// Check if we should trim log files
685//
686 if (eKeep && doLFR) Trim();
687 return 0;
688}
689
690/******************************************************************************/
691/* T r i m */
692/******************************************************************************/
693
694#ifndef WIN32
695void XrdSysLogger::Trim()
696{
697 struct LogFile
698 {LogFile *next;
699 char *fn;
700 off_t sz;
701 time_t tm;
702
703 LogFile(char *xfn, off_t xsz, time_t xtm)
704 {fn = (xfn ? strdup(xfn) : 0); sz = xsz; tm = xtm; next = 0;}
705 ~LogFile()
706 {if (fn) free(fn);
707 if (next) delete next;
708 }
709 } logList(0,0,0);
710
711 struct LogFile *logEnt, *logPrev, *logNow;
712 char eBuff[2048], logFN[MAXNAMELEN+8], logDir[MAXPATHLEN+8], *logSfx;
713 struct dirent *dp;
714 struct stat buff;
715 long long totSz = 0;
716 int n,rc, totNum= 0;
717 DIR *DFD;
718
719// Ignore this call if we are not deleting log files
720//
721 if (!eKeep) return;
722
723// Construct the directory path
724//
725 if (!ePath) return;
726 strcpy(logDir, ePath);
727 if (!(logSfx = rindex(logDir, '/'))) return;
728 *logSfx = '\0';
729 strcpy(logFN, logSfx+1);
730 n = strlen(logFN);
731
732// Open the directory
733//
734 if (!(DFD = opendir(logDir)))
735 {int msz = snprintf(eBuff, 2048, "Error %d (%s) opening log directory %s\n",
736 errno, XrdSysE2T(errno), logDir);
737 putEmsg(eBuff, msz);
738 return;
739 }
740 *logSfx++ = '/';
741
742// Record all of the log files currently in this directory
743//
744 errno = 0;
745 while((dp = readdir(DFD)))
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;
749
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;}
755
756 logPrev->next = logEnt;
757 logEnt->next = logNow;
758 }
759
760// Check if we received an error
761//
762 rc = errno; closedir(DFD);
763 if (rc)
764 {int msz = snprintf(eBuff, 2048, "Error %d (%s) reading log directory %s\n",
765 rc, XrdSysE2T(rc), logDir);
766 putEmsg(eBuff, msz);
767 return;
768 }
769
770// If there is only one log file here no need to
771//
772 if (totNum <= 1) return;
773
774// Check if we need to trim log files
775//
776 if (eKeep < 0)
777 {if ((totNum += eKeep) <= 0) return;
778 } else {
779 if (totSz <= eKeep) return;
780 logNow = logList.next; totNum = 0;
781 while(logNow && totSz > eKeep)
782 {totNum++; totSz -= logNow->sz; logNow = logNow->next;}
783 }
784
785// Now start deleting log files
786//
787 logNow = logList.next;
788 while(logNow && totNum--)
789 {strcpy(logSfx, logNow->fn);
790 if (unlink(logDir))
791 rc = snprintf(eBuff, 2048, "Error %d (%s) removing log file %s\n",
792 errno, XrdSysE2T(errno), logDir);
793 else rc = snprintf(eBuff, 2048, "Removed log file %s\n", logDir);
794 putEmsg(eBuff, rc);
795 logNow = logNow->next;
796 }
797}
798#else
799void XrdSysLogger::Trim()
800{
801}
802#endif
803
804/******************************************************************************/
805/* z H a n d l e r */
806/******************************************************************************/
807#include <poll.h>
808
810{
811 mmMsg *mP;
812 sigset_t sigset;
813 pthread_t tid;
814 int signo, rc;
815 Task *tP;
816
817// If we will be handling via signals, set it up now
818//
819 if (eInt < 0 && !fifoFN)
820 {signo = -eInt;
821 if ((sigemptyset(&sigset) == -1)
822 || (sigaddset(&sigset,signo) == -1))
823 {rc = errno;
824 BLAB("Unable to use logfile signal " <<signo <<"; " <<XrdSysE2T(rc));
825 eInt = 0;
826 }
827 }
828
829// This is a perpetual loop to handle the log file
830//
831 while(1)
832 { if (fifoFN) FifoWait();
833 else if (eInt >= 0) XrdSysTimer::Wait4Midnight();
834 else if ((sigwait(&sigset, &signo) == -1))
835 {rc = errno;
836 BLAB("Unable to wait on logfile signal " <<signo
837 <<"; " <<XrdSysE2T(rc));
838 eInt = 0;
839 continue;
840 }
841
842 Logger_Mutex.Lock();
843 ReBind();
844
845 mP = msgList;
846 while(mP)
847 {putEmsg(mP->msg, mP->mlen);
848 mP = mP->next;
849 }
850 tP = taskQ;
851 Logger_Mutex.UnLock();
852
853 if (tP)
854 {if (XrdSysThread::Run(&tid, XrdSysLoggerMN, (void *)tP, 0,
855 "Midnight Ringer Task"))
856 {char eBuff[256];
857 rc = sprintf(eBuff, "Error %d (%s) running ringer task.\n",
858 errno, XrdSysE2T(errno));
859 putEmsg(eBuff, rc);
860 }
861 }
862 }
863}
struct stat Stat
Definition XrdCks.cc:49
#define access(a, b)
Definition XrdPosix.hh:44
#define close(a)
Definition XrdPosix.hh:48
#define opendir(a)
Definition XrdPosix.hh:78
#define open
Definition XrdPosix.hh:76
#define writev(a, b, c)
Definition XrdPosix.hh:117
#define closedir(a)
Definition XrdPosix.hh:50
#define unlink(a)
Definition XrdPosix.hh:113
#define stat(a, b)
Definition XrdPosix.hh:101
#define rename(a, b)
Definition XrdPosix.hh:92
#define readdir(a)
Definition XrdPosix.hh:86
#define read(a, b, c)
Definition XrdPosix.hh:82
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
#define BLAB(x)
void * XrdSysLoggerRT(void *carg)
void * XrdSysLoggerMN(void *carg)
void Add(XrdOucTList *tP)
virtual void Ring()=0
This method gets called at midnight.
static const int onFifo
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 bool SigBlock()
static int GetSigNum(const char *sname)
XrdSysLoggerRP(XrdSysLogger *lp)
XrdSysLogger * logger
XrdSysSemaphore active