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 = XrdSysFD_Dup(ErrFD);
165 Bind(logFN, 1);
166 }
167}
168
169/******************************************************************************/
170/* A d d M s g */
171/******************************************************************************/
172
173void XrdSysLogger::AddMsg(const char *msg)
174{
175 mmMsg *tP, *nP = new mmMsg;
176
177// Fill out new message
178//
179 nP->next = 0;
180 nP->msg = strdup(msg);
181 nP->mlen = strlen(msg);
182
183// Add new line character if one is missing (we steal the null byte for this)
184//
185 if (nP->mlen > 1 && nP->msg[nP->mlen-1] != '\n')
186 {nP->msg[nP->mlen] = '\n'; nP->mlen += 1;}
187
188// Add this message to the end of the list
189//
190 Logger_Mutex.Lock();
191 if (!(tP = msgList)) msgList = nP;
192 else {while(tP->next) tP = tP->next;
193 tP->next = nP;
194 }
195 Logger_Mutex.UnLock();
196}
197
198/******************************************************************************/
199/* A t M i d n i g h t */
200/******************************************************************************/
201
203{
204
205// Place this task on the task queue
206//
207 Logger_Mutex.Lock();
208 mnTask->next = taskQ;
209 taskQ = mnTask;
210 Logger_Mutex.UnLock();
211}
212
213/******************************************************************************/
214/* B i n d */
215/******************************************************************************/
216
217int XrdSysLogger::Bind(const char *path, int lfh)
218{
219 XrdSysLoggerRP rtParms(this);
220 int rc;
221
222// Kill logfile handler thread if parameters will be changing
223//
224 if (lfh > 0) lfh = 1;
225 if (lfhTID && (eInt != lfh || !path))
226 {XrdSysThread::Kill(lfhTID);
227 lfhTID = 0;
228 }
229
230// Bind to stderr if no path specified
231//
232 if (ePath) free(ePath);
233 eInt = 0;
234 ePath = 0;
235 if (fifoFN) free(fifoFN);
236 fifoFN = 0; doLFR = false;
237 if (!path) return 0;
238
239// Bind to a log file
240//
241 eInt = lfh;
242 ePath = strdup(path);
243 doLFR = (lfh > 0);
244 if ((rc = ReBind(0))) return rc;
245
246// Lock the logs if XRootD is suppose to handle log rotation itself
247//
248 rc = HandleLogRotateLock( doLFR );
249 if( rc )
250 return -rc;
251
252// Handle specifics of lofile rotation
253//
254 if (eInt == onFifo) {if ((rc = FifoMake())) return -rc;}
255 else if (eInt < 0 && !XrdSysUtils::SigBlock(-eInt))
256 {rc = errno;
257 BLAB("Unable to block logfile signal " <<-eInt <<"; "
258 <<XrdSysE2T(rc));
259 eInt = 0;
260 return -rc;
261 }
262
263// Start a log rotation thread
264//
265 rc = XrdSysThread::Run(&lfhTID, XrdSysLoggerRT, (void *)&rtParms, 0,
266 "Logfile handler");
267 if (!rc) rtParms.active.Wait();
268 return (rc > 0 ? -rc : rc);
269}
270
271/******************************************************************************/
272/* C a p t u r e */
273/******************************************************************************/
274
276{
277
278// Obtain the serailization mutex
279//
280 Logger_Mutex.Lock();
281
282// Set the base for capturing messages
283//
284 tFifo = tFIFO;
285
286// Release the serailization mutex
287//
288 Logger_Mutex.UnLock();
289}
290
291/******************************************************************************/
292/* P a r s e K e e p */
293/******************************************************************************/
294
295int XrdSysLogger::ParseKeep(const char *arg)
296{
297 char *eP;
298
299// First check to see if this is a sig type
300//
301 eKeep = 0;
302 if (isalpha(*arg))
303 {if (!strcmp(arg, "fifo")) return onFifo;
304 return -XrdSysUtils::GetSigNum(arg);
305 }
306
307// Process an actual keep count
308//
309 eKeep = strtoll(arg, &eP, 10);
310 if (!(*eP) || eKeep < 0) {eKeep = -eKeep; return 1;}
311
312// Process an actual keep size
313//
314 if (*(eP+1)) return 0;
315 if (*eP == 'k' || *eP == 'K') eKeep *= 1024LL;
316 else if (*eP == 'm' || *eP == 'M') eKeep *= 1024LL*1024LL;
317 else if (*eP == 'g' || *eP == 'G') eKeep *= 1024LL*1024LL*1024LL;
318 else if (*eP == 't' || *eP == 'T') eKeep *= 1024LL*1024LL*1024LL*1024LL;
319 else return 0;
320
321// All done
322//
323 return 1;
324}
325
326/******************************************************************************/
327/* P u t */
328/******************************************************************************/
329
330void XrdSysLogger::Put(int iovcnt, struct iovec *iov)
331{
332 struct timeval tVal;
333 unsigned long tID = XrdSysThread::Num();
334 int retc;
335 char tbuff[32];
336
337// Get current time
338//
339 gettimeofday(&tVal, 0);
340
341// Forward the message if there is a plugin involved here
342//
343 if (doForward)
344 {bool xEnd;
345 if (iov[0].iov_base) xEnd = XrdSysLogging::Forward(tVal,tID,iov,iovcnt);
346 else xEnd = XrdSysLogging::Forward(tVal, tID, &iov[1], iovcnt-1);
347 if (xEnd) return;
348 }
349
350// Prefix message with time if calle wants it so
351//
352 if (!iov[0].iov_base)
353 {iov[0].iov_base = tbuff;
354 iov[0].iov_len = TimeStamp(tVal, tID, tbuff, sizeof(tbuff), hiRes);
355 }
356
357// Obtain the serailization mutex if need be
358//
359 Logger_Mutex.Lock();
360
361// If we are capturing messages, do so now
362//
363 if (tFifo)
364 {Snatch(iov, iovcnt);
365 Logger_Mutex.UnLock();
366 return;
367 }
368
369// In theory, writev may write out a partial list. This rarely happens in
370// practice and so we ignore that possibility (recovery is pretty tough).
371//
372 do { retc = writev(eFD, (const struct iovec *)iov, iovcnt);}
373 while (retc < 0 && errno == EINTR);
374
375// Release the serailization mutex if need be
376//
377 Logger_Mutex.UnLock();
378}
379
380/******************************************************************************/
381/* Private: T i m e */
382/******************************************************************************/
383
384int XrdSysLogger::Time(char *tbuff)
385{
386 struct timeval tVal;
387 const int minblen = 32;
388 struct tm tNow;
389 int i;
390
391// Get the current time
392//
393 gettimeofday(&tVal, 0);
394
395// Format the time in human terms
396//
397 localtime_r((const time_t *) &tVal.tv_sec, &tNow);
398
399// Choose appropriate output
400//
401 if (hiRes)
402 {i = snprintf(tbuff, minblen, "%02d%02d%02d %02d:%02d:%02d.%06d %03ld ",
403 tNow.tm_year-100, tNow.tm_mon+1, tNow.tm_mday,
404 tNow.tm_hour, tNow.tm_min, tNow.tm_sec,
405 static_cast<int>(tVal.tv_usec), XrdSysThread::Num());
406 } else {
407 i = snprintf(tbuff, minblen, "%02d%02d%02d %02d:%02d:%02d %03ld ",
408 tNow.tm_year-100, tNow.tm_mon+1, tNow.tm_mday,
409 tNow.tm_hour, tNow.tm_min, tNow.tm_sec,
411 }
412 return (i >= minblen ? minblen-1 : i);
413}
414
415/******************************************************************************/
416/* Private: T i m e S t a m p */
417/******************************************************************************/
418
419int XrdSysLogger::TimeStamp(struct timeval &tVal, unsigned long tID,
420 char *tbuff, int tbsz, bool hires)
421{
422 struct tm tNow;
423 int i;
424
425// Validate tbuff size
426//
427 if (tbsz <= 0) return 0;
428
429// Format the time in human terms
430//
431 localtime_r((const time_t *) &tVal.tv_sec, &tNow);
432
433// Choose appropriate output
434//
435 if (hires)
436 {i = snprintf(tbuff, tbsz, "%02d%02d%02d %02d:%02d:%02d.%06d %03ld ",
437 tNow.tm_year-100, tNow.tm_mon+1, tNow.tm_mday,
438 tNow.tm_hour, tNow.tm_min, tNow.tm_sec,
439 static_cast<int>(tVal.tv_usec), tID);
440 } else {
441 i = snprintf(tbuff, tbsz, "%02d%02d%02d %02d:%02d:%02d %03ld ",
442 tNow.tm_year-100, tNow.tm_mon+1, tNow.tm_mday,
443 tNow.tm_hour, tNow.tm_min, tNow.tm_sec, tID);
444 }
445 return (i >= tbsz ? tbsz-1 : i);
446}
447
448/******************************************************************************/
449/* P r i v a t e M e t h o d s */
450/******************************************************************************/
451/******************************************************************************/
452/* F i f o M a k e */
453/******************************************************************************/
454
455int XrdSysLogger::FifoMake()
456{
457 struct stat Stat;
458 char buff[2048], *slash;
459 int n, rc, saveInt = eInt;
460
461// Assume failure (just to keep down the code)
462//
463 eInt = 0;
464
465// Construct the fifo name
466//
467 if (!(slash = rindex(ePath, '/')))
468 {*buff = '.';
469 strcpy(buff+1, ePath);
470 } else {
471 n = slash - ePath + 1;
472 strncpy(buff, ePath, n);
473 buff[n] = '.';
474 strcpy(&buff[n+1], slash+1);
475 }
476
477// Check if the fifo exists and is usable or that we can create it
478//
479 if (!stat(buff, &Stat))
480 { if (!S_ISFIFO(Stat.st_mode))
481 {BLAB("Logfile fifo " <<buff <<" exists but is not a fifo");
482 rc = EEXIST;
483 }
484 else if (access(buff, R_OK))
485 {BLAB("Unable to access " <<buff);
486 rc = EACCES;
487 }
488 else rc = 0;
489 if (rc)
490 {if (unlink(buff))
491 {BLAB("Unable to remove " <<buff <<"; " <<XrdSysE2T(errno));
492 return rc;
493 } else {
494 BLAB(buff <<" has been removed");
495 rc = ENOENT;
496 }
497 }
498 } else {
499 rc = errno;
500 if (rc != ENOENT)
501 {BLAB("Unable to stat " <<buff <<"; " <<XrdSysE2T(rc));
502 return rc;
503 }
504 }
505
506// Now try to create the fifo if we actually need to
507//
508 if (rc == ENOENT)
509 {if (mkfifo(buff, S_IRUSR|S_IWUSR))
510 {rc = errno;
511 BLAB("Unable to create logfile fifo " <<buff <<"; " <<XrdSysE2T(rc));
512 return rc;
513 }
514 }
515
516// Save the fifo path restore eInt
517//
518 fifoFN = strdup(buff);
519 eInt = saveInt;
520 return 0;
521}
522
523/******************************************************************************/
524/* H a n d l e L o g R o t a t e L o c k */
525/******************************************************************************/
526int XrdSysLogger::HandleLogRotateLock( bool dorotate )
527{
528 if( !ePath ) return 0;
529
530 char *end = rindex(ePath, '/');
531 const std::string lckPath = (end ? std::string(ePath,end+1)+".lock" : ".lock");
532 int rc = unlink( lckPath.c_str() );
533 if( rc && errno != ENOENT )
534 {
535 BLAB( "The logfile lock (" << lckPath.c_str() << ") exists and cannot be removed: " << XrdSysE2T( errno ) );
536 return EEXIST;
537 }
538
539 if( dorotate )
540 {
541 rc = open( lckPath.c_str(), O_CREAT, 0644 );
542 if( rc < 0 )
543 {
544 BLAB( "Failed to create the logfile lock (" << lckPath.c_str() << "): " << XrdSysE2T( errno ) );
545 return errno;
546 }
547 close( rc );
548 }
549
550 return 0;
551}
552
553/******************************************************************************/
554/* R m L o g R o t a t e L o c k */
555/******************************************************************************/
556void XrdSysLogger::RmLogRotateLock()
557{
558 if( !ePath ) return;
559
560 char *end = rindex(ePath, '/') + 1;
561 const std::string lckPath = std::string( ePath, end ) + ".lock";
562 unlink( lckPath.c_str() );
563}
564
565/******************************************************************************/
566/* F i f o W a i t */
567/******************************************************************************/
568
569void XrdSysLogger::FifoWait()
570{
571 char buff[64];
572 int pipeFD, rc;
573
574// Open the fifo. We can't have this block as we need to make sure it is
575// closed on EXEC as fast as possible (Linux has a non-portable solution).
576//
577 if ((pipeFD = XrdSysFD_Open(fifoFN, O_RDONLY)) < 0)
578 {rc = errno;
579 BLAB("Unable to open logfile fifo " <<fifoFN <<"; " <<XrdSysE2T(rc));
580 eInt = 0;
581 free(fifoFN); fifoFN = 0;
582 return;
583 }
584
585// Wait for read, this will block. If we got an EOF then something went wrong!
586//
587 if (!read(pipeFD, buff, sizeof(buff)))
588 {BLAB("Unexpected EOF on logfile fifo " <<fifoFN);
589 eInt = 0;
590 }
591 close(pipeFD);
592}
593
594/******************************************************************************/
595/* p u t E m s g */
596/******************************************************************************/
597
598// This internal logging method is used when the caller already has the mutex!
599
600void XrdSysLogger::putEmsg(char *msg, int msz)
601{
602 unsigned long tID = XrdSysThread::Num();
603 char tbuff[32];
604 struct timeval tVal;
605 struct iovec eVec[2] = {{tbuff, 0}, {msg, (size_t)msz}};
606 int retc;
607
608// Get current time
609//
610 gettimeofday(&tVal, 0);
611
612// Forward the message if there is a plugin involved here
613//
614 if (doForward && XrdSysLogging::Forward(tVal, tID, &eVec[1], 1)) return;
615
616// Prefix message with time
617//
618 eVec[0].iov_len = TimeStamp(tVal, tID, tbuff, sizeof(tbuff), hiRes);
619
620// In theory, writev may write out a partial list. This rarely happens in
621// practice and so we ignore that possibility (recovery is pretty tough).
622//
623 do { retc = writev(eFD, (const struct iovec *)eVec, 2);}
624 while (retc < 0 && errno == EINTR);
625}
626
627/******************************************************************************/
628/* R e B i n d */
629/******************************************************************************/
630
631int XrdSysLogger::ReBind(int dorename)
632{
633 const char seq[] = "0123456789";
634 unsigned int i;
635 int newfd;
636 struct tm nowtime;
637 char *bp, buff[MAXPATHLEN+MAXNAMELEN];
638 struct stat bf;
639
640// Rename the file to be of the form yyyymmdd corresponding to the date it was
641// opened. We will add a sequence number (.x) if a conflict occurs.
642//
643 if (dorename && doLFR)
644 {strcpy(buff, ePath);
645 bp = buff+strlen(ePath);
646 *bp++ = '.';
647 strncpy(bp, Filesfx, 8);
648 bp += 8;
649 *bp = '\0'; *(bp+2) = '\0';
650 for (i = 0; i < sizeof(seq) && !stat(buff, &bf); i++)
651 {*bp = '.'; *(bp+1) = (char)seq[i];}
652 if (i < sizeof(seq)) rename(ePath, buff);
653 }
654
655// Compute the suffix for the file
656//
657 if (doLFR)
658 {time_t eNow = time(0);
659 localtime_r((const time_t *) &eNow, &nowtime);
660 sprintf(buff, "%4d%02d%02d", nowtime.tm_year+1900, nowtime.tm_mon+1,
661 nowtime.tm_mday);
662 memcpy(Filesfx, buff, 8);
663 }
664
665// Open the file for output. Note that we can still leak a file descriptor
666// if a thread forks a process before we are able to do the fcntl(), sigh.
667//
668 if ((newfd = XrdSysFD_Open(ePath,O_WRONLY|O_APPEND|O_CREAT,0644)) < 0)
669 return -errno;
670
671// Now set the file descriptor to be the same as the error FD. This will
672// close the previously opened file, if any.
673//
674 if (dup2(newfd, eFD) < 0)
675 {int rc = errno;
676 close(newfd);
677 return -rc;
678 }
679 close(newfd);
680
681// Check if we should trim log files
682//
683 if (eKeep && doLFR) Trim();
684 return 0;
685}
686
687/******************************************************************************/
688/* T r i m */
689/******************************************************************************/
690
691#ifndef WIN32
692void XrdSysLogger::Trim()
693{
694 struct LogFile
695 {LogFile *next;
696 char *fn;
697 off_t sz;
698 time_t tm;
699
700 LogFile(char *xfn, off_t xsz, time_t xtm)
701 {fn = (xfn ? strdup(xfn) : 0); sz = xsz; tm = xtm; next = 0;}
702 ~LogFile()
703 {if (fn) free(fn);
704 if (next) delete next;
705 }
706 } logList(0,0,0);
707
708 struct LogFile *logEnt, *logPrev, *logNow;
709 char eBuff[2048], logFN[MAXNAMELEN+8], logDir[MAXPATHLEN+8], *logSfx;
710 struct dirent *dp;
711 struct stat buff;
712 long long totSz = 0;
713 int n,rc, totNum= 0;
714 DIR *DFD;
715
716// Ignore this call if we are not deleting log files
717//
718 if (!eKeep) return;
719
720// Construct the directory path
721//
722 if (!ePath) return;
723 strcpy(logDir, ePath);
724 if (!(logSfx = rindex(logDir, '/'))) return;
725 *logSfx = '\0';
726 strcpy(logFN, logSfx+1);
727 n = strlen(logFN);
728
729// Open the directory
730//
731 if (!(DFD = opendir(logDir)))
732 {int msz = snprintf(eBuff, 2048, "Error %d (%s) opening log directory %s\n",
733 errno, XrdSysE2T(errno), logDir);
734 putEmsg(eBuff, msz);
735 return;
736 }
737 *logSfx++ = '/';
738
739// Record all of the log files currently in this directory
740//
741 errno = 0;
742 while((dp = readdir(DFD)))
743 {if (strncmp(dp->d_name, logFN, n)) continue;
744 strcpy(logSfx, dp->d_name);
745 if (stat(logDir, &buff) || !(buff.st_mode & S_IFREG)) continue;
746
747 totNum++; totSz += buff.st_size;
748 logEnt = new LogFile(dp->d_name, buff.st_size, buff.st_mtime);
749 logPrev = &logList; logNow = logList.next;
750 while(logNow && logNow->tm < buff.st_mtime)
751 {logPrev = logNow; logNow = logNow->next;}
752
753 logPrev->next = logEnt;
754 logEnt->next = logNow;
755 }
756
757// Check if we received an error
758//
759 rc = errno; closedir(DFD);
760 if (rc)
761 {int msz = snprintf(eBuff, 2048, "Error %d (%s) reading log directory %s\n",
762 rc, XrdSysE2T(rc), logDir);
763 putEmsg(eBuff, msz);
764 return;
765 }
766
767// If there is only one log file here no need to
768//
769 if (totNum <= 1) return;
770
771// Check if we need to trim log files
772//
773 if (eKeep < 0)
774 {if ((totNum += eKeep) <= 0) return;
775 } else {
776 if (totSz <= eKeep) return;
777 logNow = logList.next; totNum = 0;
778 while(logNow && totSz > eKeep)
779 {totNum++; totSz -= logNow->sz; logNow = logNow->next;}
780 }
781
782// Now start deleting log files
783//
784 logNow = logList.next;
785 while(logNow && totNum--)
786 {strcpy(logSfx, logNow->fn);
787 if (unlink(logDir))
788 rc = snprintf(eBuff, 2048, "Error %d (%s) removing log file %s\n",
789 errno, XrdSysE2T(errno), logDir);
790 else rc = snprintf(eBuff, 2048, "Removed log file %s\n", logDir);
791 putEmsg(eBuff, rc);
792 logNow = logNow->next;
793 }
794}
795#else
796void XrdSysLogger::Trim()
797{
798}
799#endif
800
801/******************************************************************************/
802/* z H a n d l e r */
803/******************************************************************************/
804#include <poll.h>
805
807{
808 mmMsg *mP;
809 sigset_t sigset;
810 pthread_t tid;
811 int signo, rc;
812 Task *tP;
813
814// If we will be handling via signals, set it up now
815//
816 if (eInt < 0 && !fifoFN)
817 {signo = -eInt;
818 if ((sigemptyset(&sigset) == -1)
819 || (sigaddset(&sigset,signo) == -1))
820 {rc = errno;
821 BLAB("Unable to use logfile signal " <<signo <<"; " <<XrdSysE2T(rc));
822 eInt = 0;
823 }
824 }
825
826// This is a perpetual loop to handle the log file
827//
828 while(1)
829 { if (fifoFN) FifoWait();
830 else if (eInt >= 0) XrdSysTimer::Wait4Midnight();
831 else if ((sigwait(&sigset, &signo) == -1))
832 {rc = errno;
833 BLAB("Unable to wait on logfile signal " <<signo
834 <<"; " <<XrdSysE2T(rc));
835 eInt = 0;
836 continue;
837 }
838
839 Logger_Mutex.Lock();
840 ReBind();
841
842 mP = msgList;
843 while(mP)
844 {putEmsg(mP->msg, mP->mlen);
845 mP = mP->next;
846 }
847 tP = taskQ;
848 Logger_Mutex.UnLock();
849
850 if (tP)
851 {if (XrdSysThread::Run(&tid, XrdSysLoggerMN, (void *)tP, 0,
852 "Midnight Ringer Task"))
853 {char eBuff[256];
854 rc = sprintf(eBuff, "Error %d (%s) running ringer task.\n",
855 errno, XrdSysE2T(errno));
856 putEmsg(eBuff, rc);
857 }
858 }
859 }
860}
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