runit/*: get rid of tai[a] time abstraction, it's too bloaty.
text data bss dec hex filename 772537 1058 11092 784687 bf92f busybox.t0/busybox 772459 1058 11060 784577 bf8c1 busybox.t1/busybox 772326 1058 11028 784412 bf81c busybox.t2/busybox 772158 1058 10980 784196 bf744 busybox.t3/busybox 771490 1055 10988 783533 bf4ad busybox.t4/busybox
This commit is contained in:
198
runit/svlogd.c
198
runit/svlogd.c
@@ -33,6 +33,10 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libbb.h"
|
||||
#include "runit_lib.h"
|
||||
|
||||
#define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0)
|
||||
|
||||
#define FMT_PTIME 30
|
||||
|
||||
static unsigned verbose;
|
||||
static int linemax = 1000;
|
||||
////static int buflen = 1024;
|
||||
@@ -41,7 +45,7 @@ static int linelen;
|
||||
static char **fndir;
|
||||
static int fdwdir;
|
||||
static int wstat;
|
||||
static struct taia trotate;
|
||||
static unsigned nearest_rotate;
|
||||
|
||||
static char *line;
|
||||
static smallint exitasap;
|
||||
@@ -55,7 +59,6 @@ static char repl;
|
||||
static const char *replace = "";
|
||||
|
||||
static sigset_t *blocked_sigset;
|
||||
static iopause_fd input;
|
||||
static int fl_flag_0;
|
||||
|
||||
static struct logdir {
|
||||
@@ -68,14 +71,13 @@ static struct logdir {
|
||||
unsigned sizemax;
|
||||
unsigned nmax;
|
||||
unsigned nmin;
|
||||
/* int (not long) because of taia_uint() usage: */
|
||||
unsigned tmax;
|
||||
unsigned rotate_period;
|
||||
int ppid;
|
||||
int fddir;
|
||||
int fdcur;
|
||||
FILE* filecur; ////
|
||||
int fdlock;
|
||||
struct taia trotate;
|
||||
unsigned next_rotate;
|
||||
char fnsave[FMT_PTIME];
|
||||
char match;
|
||||
char matcherr;
|
||||
@@ -128,6 +130,50 @@ static char* wstrdup(const char *str)
|
||||
return s;
|
||||
}
|
||||
|
||||
/*** ex fmt_ptime.[ch] ***/
|
||||
|
||||
/* NUL terminated */
|
||||
static void fmt_time_human_30nul(char *s)
|
||||
{
|
||||
struct tm *t;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
t = gmtime(&(tv.tv_sec));
|
||||
sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%06u000",
|
||||
(unsigned)(1900 + t->tm_year),
|
||||
(unsigned)(t->tm_mon + 1),
|
||||
(unsigned)(t->tm_mday),
|
||||
(unsigned)(t->tm_hour),
|
||||
(unsigned)(t->tm_min),
|
||||
(unsigned)(t->tm_sec),
|
||||
(unsigned)(tv.tv_usec)
|
||||
);
|
||||
/* 4+1 + 2+1 + 2+1 + 2+1 + 2+1 + 2+1 + 9 = */
|
||||
/* 5 + 3 + 3 + 3 + 3 + 3 + 9 = */
|
||||
/* 20 (up to '.' inclusive) + 9 (not including '\0') */
|
||||
}
|
||||
|
||||
/* NOT terminated! */
|
||||
static void fmt_time_bernstein_25(char *s)
|
||||
{
|
||||
uint32_t pack[3];
|
||||
struct timeval tv;
|
||||
unsigned sec_hi;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
sec_hi = (0x400000000000000aULL + tv.tv_sec) >> 32;
|
||||
tv.tv_sec = (time_t)(0x400000000000000aULL) + tv.tv_sec;
|
||||
tv.tv_usec *= 1000;
|
||||
/* Network order is big-endian: most significant byte first.
|
||||
* This is exactly what we want here */
|
||||
pack[0] = htonl(sec_hi);
|
||||
pack[1] = htonl(tv.tv_sec);
|
||||
pack[2] = htonl(tv.tv_usec);
|
||||
*s++ = '@';
|
||||
bin2hex(s, (char*)pack, 12);
|
||||
}
|
||||
|
||||
static unsigned processorstart(struct logdir *ld)
|
||||
{
|
||||
int pid;
|
||||
@@ -264,15 +310,15 @@ static void rmoldest(struct logdir *ld)
|
||||
static unsigned rotate(struct logdir *ld)
|
||||
{
|
||||
struct stat st;
|
||||
struct taia now;
|
||||
unsigned now;
|
||||
|
||||
if (ld->fddir == -1) {
|
||||
ld->tmax = 0;
|
||||
ld->rotate_period = 0;
|
||||
return 0;
|
||||
}
|
||||
if (ld->ppid)
|
||||
while (!processorstop(ld))
|
||||
/* wait */;
|
||||
continue;
|
||||
|
||||
while (fchdir(ld->fddir) == -1)
|
||||
pause2cannot("change directory, want rotate", ld->name);
|
||||
@@ -284,17 +330,16 @@ static unsigned rotate(struct logdir *ld)
|
||||
ld->fnsave[26] = 'u';
|
||||
ld->fnsave[27] = '\0';
|
||||
do {
|
||||
taia_now(&now);
|
||||
fmt_taia25(ld->fnsave, &now);
|
||||
fmt_time_bernstein_25(ld->fnsave);
|
||||
errno = 0;
|
||||
stat(ld->fnsave, &st);
|
||||
} while (errno != ENOENT);
|
||||
|
||||
if (ld->tmax && taia_less(&ld->trotate, &now)) {
|
||||
taia_uint(&ld->trotate, ld->tmax);
|
||||
taia_add(&ld->trotate, &now, &ld->trotate);
|
||||
if (taia_less(&ld->trotate, &trotate))
|
||||
trotate = ld->trotate;
|
||||
now = monotonic_sec();
|
||||
if (ld->rotate_period && LESS(ld->next_rotate, now)) {
|
||||
ld->next_rotate = now + ld->rotate_period;
|
||||
if (LESS(ld->next_rotate, nearest_rotate))
|
||||
nearest_rotate = ld->next_rotate;
|
||||
}
|
||||
|
||||
if (ld->size > 0) {
|
||||
@@ -425,11 +470,13 @@ static void logdir_close(struct logdir *ld)
|
||||
static unsigned logdir_open(struct logdir *ld, const char *fn)
|
||||
{
|
||||
char buf[128];
|
||||
struct taia now;
|
||||
unsigned now;
|
||||
char *new, *s, *np;
|
||||
int i;
|
||||
struct stat st;
|
||||
|
||||
now = monotonic_sec();
|
||||
|
||||
ld->fddir = open(fn, O_RDONLY|O_NDELAY);
|
||||
if (ld->fddir == -1) {
|
||||
warn2("cannot open log directory", (char*)fn);
|
||||
@@ -456,7 +503,7 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
|
||||
ld->size = 0;
|
||||
ld->sizemax = 1000000;
|
||||
ld->nmax = ld->nmin = 10;
|
||||
ld->tmax = 0;
|
||||
ld->rotate_period = 0;
|
||||
ld->name = (char*)fn;
|
||||
ld->ppid = 0;
|
||||
ld->match = '+';
|
||||
@@ -468,7 +515,8 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
|
||||
if (i < 0 && errno != ENOENT)
|
||||
bb_perror_msg(WARNING": %s/config", ld->name);
|
||||
if (i > 0) {
|
||||
if (verbose) bb_error_msg(INFO"read: %s/config", ld->name);
|
||||
if (verbose)
|
||||
bb_error_msg(INFO"read: %s/config", ld->name);
|
||||
s = buf;
|
||||
while (s) {
|
||||
np = strchr(s, '\n');
|
||||
@@ -508,12 +556,11 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
|
||||
/*{ "d", 24*60*60 },*/
|
||||
{ }
|
||||
};
|
||||
ld->tmax = xatou_sfx(&s[1], mh_suffixes);
|
||||
if (ld->tmax) {
|
||||
taia_uint(&ld->trotate, ld->tmax);
|
||||
taia_add(&ld->trotate, &now, &ld->trotate);
|
||||
if (!tmaxflag || taia_less(&ld->trotate, &trotate))
|
||||
trotate = ld->trotate;
|
||||
ld->rotate_period = xatou_sfx(&s[1], mh_suffixes);
|
||||
if (ld->rotate_period) {
|
||||
ld->next_rotate = now + ld->rotate_period;
|
||||
if (!tmaxflag || LESS(ld->next_rotate, nearest_rotate))
|
||||
nearest_rotate = ld->next_rotate;
|
||||
tmaxflag = 1;
|
||||
}
|
||||
break;
|
||||
@@ -544,8 +591,7 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
|
||||
ld->fnsave[26] = 'u';
|
||||
ld->fnsave[27] = '\0';
|
||||
do {
|
||||
taia_now(&now);
|
||||
fmt_taia25(ld->fnsave, &now);
|
||||
fmt_time_bernstein_25(ld->fnsave);
|
||||
errno = 0;
|
||||
stat(ld->fnsave, &st);
|
||||
} while (errno != ENOENT);
|
||||
@@ -589,17 +635,17 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
|
||||
|
||||
static void logdirs_reopen(void)
|
||||
{
|
||||
struct taia now;
|
||||
int l;
|
||||
int ok = 0;
|
||||
|
||||
tmaxflag = 0;
|
||||
taia_now(&now);
|
||||
for (l = 0; l < dirn; ++l) {
|
||||
logdir_close(&dir[l]);
|
||||
if (logdir_open(&dir[l], fndir[l])) ok = 1;
|
||||
if (logdir_open(&dir[l], fndir[l]))
|
||||
ok = 1;
|
||||
}
|
||||
if (!ok) fatalx("no functional log directories");
|
||||
if (!ok)
|
||||
fatalx("no functional log directories");
|
||||
}
|
||||
|
||||
/* Will look good in libbb one day */
|
||||
@@ -614,42 +660,55 @@ static ssize_t ndelay_read(int fd, void *buf, size_t count)
|
||||
}
|
||||
|
||||
/* Used for reading stdin */
|
||||
static int buffer_pread(int fd, char *s, unsigned len, struct taia *now)
|
||||
static int buffer_pread(int fd, char *s, unsigned len)
|
||||
{
|
||||
unsigned now;
|
||||
struct pollfd input;
|
||||
int i;
|
||||
|
||||
if (rotateasap) {
|
||||
for (i = 0; i < dirn; ++i)
|
||||
rotate(dir+i);
|
||||
rotateasap = 0;
|
||||
}
|
||||
if (exitasap) {
|
||||
if (linecomplete)
|
||||
return 0;
|
||||
len = 1;
|
||||
}
|
||||
if (reopenasap) {
|
||||
logdirs_reopen();
|
||||
reopenasap = 0;
|
||||
}
|
||||
taia_uint(&trotate, 2744);
|
||||
taia_add(&trotate, now, &trotate);
|
||||
for (i = 0; i < dirn; ++i)
|
||||
if (dir[i].tmax) {
|
||||
if (taia_less(&dir[i].trotate, now))
|
||||
rotate(dir+i);
|
||||
if (taia_less(&dir[i].trotate, &trotate))
|
||||
trotate = dir[i].trotate;
|
||||
}
|
||||
input.fd = 0;
|
||||
input.events = POLLIN|POLLHUP|POLLERR;
|
||||
|
||||
do {
|
||||
if (rotateasap) {
|
||||
for (i = 0; i < dirn; ++i)
|
||||
rotate(dir + i);
|
||||
rotateasap = 0;
|
||||
}
|
||||
if (exitasap) {
|
||||
if (linecomplete)
|
||||
return 0;
|
||||
len = 1;
|
||||
}
|
||||
if (reopenasap) {
|
||||
logdirs_reopen();
|
||||
reopenasap = 0;
|
||||
}
|
||||
now = monotonic_sec();
|
||||
nearest_rotate = now + (45 * 60 + 45);
|
||||
for (i = 0; i < dirn; ++i) {
|
||||
if (dir[i].rotate_period) {
|
||||
if (LESS(dir[i].next_rotate, now))
|
||||
rotate(dir + i);
|
||||
if (LESS(dir[i].next_rotate, nearest_rotate))
|
||||
nearest_rotate = dir[i].next_rotate;
|
||||
}
|
||||
}
|
||||
|
||||
sigprocmask(SIG_UNBLOCK, blocked_sigset, NULL);
|
||||
iopause(&input, 1, &trotate, now);
|
||||
// TODO: do not unblock/block, but use sigpending after iopause
|
||||
// to see whether there was any sig? (one syscall less...)
|
||||
i = nearest_rotate - now;
|
||||
if (i > 1000000)
|
||||
i = 1000000;
|
||||
if (i <= 0)
|
||||
i = 1;
|
||||
poll(&input, 1, i * 1000);
|
||||
sigprocmask(SIG_BLOCK, blocked_sigset, NULL);
|
||||
|
||||
i = ndelay_read(fd, s, len);
|
||||
if (i >= 0) break;
|
||||
if (i >= 0)
|
||||
break;
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno != EAGAIN) {
|
||||
warn("cannot read standard input");
|
||||
break;
|
||||
@@ -660,7 +719,8 @@ static int buffer_pread(int fd, char *s, unsigned len, struct taia *now)
|
||||
if (i > 0) {
|
||||
int cnt;
|
||||
linecomplete = (s[i-1] == '\n');
|
||||
if (!repl) return i;
|
||||
if (!repl)
|
||||
return i;
|
||||
|
||||
cnt = i;
|
||||
while (--cnt >= 0) {
|
||||
@@ -698,13 +758,15 @@ static void sig_child_handler(int sig_no)
|
||||
|
||||
if (verbose)
|
||||
bb_error_msg(INFO"sig%s received", "child");
|
||||
while ((pid = wait_nohang(&wstat)) > 0)
|
||||
for (l = 0; l < dirn; ++l)
|
||||
while ((pid = wait_nohang(&wstat)) > 0) {
|
||||
for (l = 0; l < dirn; ++l) {
|
||||
if (dir[l].ppid == pid) {
|
||||
dir[l].ppid = 0;
|
||||
processorstop(&dir[l]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sig_alarm_handler(int sig_no)
|
||||
@@ -795,8 +857,6 @@ int svlogd_main(int argc, char **argv)
|
||||
}
|
||||
/* line = xmalloc(linemax + (timestamp ? 26 : 0)); */
|
||||
fndir = argv;
|
||||
input.fd = 0;
|
||||
input.events = IOPAUSE_READ;
|
||||
/* We cannot set NONBLOCK on fd #0 permanently - this setting
|
||||
* _isn't_ per-process! It is shared among all other processes
|
||||
* with the same stdin */
|
||||
@@ -826,7 +886,6 @@ int svlogd_main(int argc, char **argv)
|
||||
|
||||
/* Each iteration processes one or more lines */
|
||||
while (1) {
|
||||
struct taia now;
|
||||
char stamp[FMT_PTIME];
|
||||
char *lineptr;
|
||||
char *printptr;
|
||||
@@ -846,8 +905,7 @@ int svlogd_main(int argc, char **argv)
|
||||
if (!np && !exitasap) {
|
||||
i = linemax - stdin_cnt; /* avail. bytes at tail */
|
||||
if (i >= 128) {
|
||||
taia_now(&now);
|
||||
i = buffer_pread(0, lineptr + stdin_cnt, i, &now);
|
||||
i = buffer_pread(0, lineptr + stdin_cnt, i);
|
||||
if (i <= 0) /* EOF or error on stdin */
|
||||
exitasap = 1;
|
||||
else {
|
||||
@@ -879,11 +937,10 @@ int svlogd_main(int argc, char **argv)
|
||||
printlen = linelen;
|
||||
printptr = lineptr;
|
||||
if (timestamp) {
|
||||
taia_now(&now);
|
||||
if (timestamp == 1)
|
||||
fmt_taia25(stamp, &now);
|
||||
fmt_time_bernstein_25(stamp);
|
||||
else /* 2: */
|
||||
fmt_ptime30nul(stamp, &now);
|
||||
fmt_time_human_30nul(stamp);
|
||||
printlen += 26;
|
||||
printptr -= 26;
|
||||
memcpy(printptr, stamp, 25);
|
||||
@@ -905,8 +962,7 @@ int svlogd_main(int argc, char **argv)
|
||||
/* read/write repeatedly until we see it */
|
||||
while (ch != '\n') {
|
||||
/* lineptr is emptied now, safe to use as buffer */
|
||||
taia_now(&now);
|
||||
stdin_cnt = exitasap ? -1 : buffer_pread(0, lineptr, linemax, &now);
|
||||
stdin_cnt = exitasap ? -1 : buffer_pread(0, lineptr, linemax);
|
||||
if (stdin_cnt <= 0) { /* EOF or error on stdin */
|
||||
exitasap = 1;
|
||||
lineptr[0] = ch = '\n';
|
||||
|
Reference in New Issue
Block a user