Change tail to use kqueue/kevent to obtain a notification when

the file changes (when doing tail -{f|F}).
This commit is contained in:
Jonathan Lemon 2000-04-16 19:04:49 +00:00
parent 3ee12e4fe3
commit b446630f2f

View File

@ -32,6 +32,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*
* $FreeBSD$
*/ */
#ifndef lint #ifndef lint
@ -43,6 +45,7 @@ static char sccsid[] = "@(#)forward.c 8.1 (Berkeley) 6/6/93";
#include <sys/time.h> #include <sys/time.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <event.h>
#include <limits.h> #include <limits.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
@ -84,9 +87,8 @@ forward(fp, style, off, sbp)
long off; long off;
struct stat *sbp; struct stat *sbp;
{ {
register int ch; int ch, add_events = 0, kq = -1;
struct timeval interval; struct kevent ev[2];
struct stat sb2;
switch(style) { switch(style) {
case FBYTES: case FBYTES:
@ -161,10 +163,12 @@ forward(fp, style, off, sbp)
break; break;
} }
/* if (fflag) {
* We pause for 1/4 second after displaying any data that has kq = kqueue();
* accumulated since we read the file. if (kq < 0)
*/ err(1, "kqueue");
add_events = 1;
}
for (;;) { for (;;) {
while ((ch = getc(fp)) != EOF) while ((ch = getc(fp)) != EOF)
@ -175,24 +179,49 @@ forward(fp, style, off, sbp)
return; return;
} }
(void)fflush(stdout); (void)fflush(stdout);
if (!fflag) if (! fflag)
break; break;
(void) usleep(250000);
clearerr(fp); clearerr(fp);
if (Fflag && fileno(fp) != STDIN_FILENO && if (add_events) {
stat(fname, &sb2) != -1) { int n = 0;
if (sb2.st_ino != sbp->st_ino || struct kevent *evp[2];
sb2.st_dev != sbp->st_dev || struct timespec ts = { 0, 0 };
sb2.st_rdev != sbp->st_rdev ||
sb2.st_nlink == 0) { if (Fflag && fileno(fp) != STDIN_FILENO) {
fp = freopen(fname, "r", fp); ev[n].ident = fileno(fp);
if (fp == NULL) { ev[n].filter = EVFILT_VNODE;
ierr(); ev[n].flags = EV_ADD | EV_ENABLE | EV_CLEAR;
break; ev[n].fflags = NOTE_DELETE | NOTE_RENAME;
} evp[n] = &ev[n];
*sbp = sb2; n++;
}
ev[n].ident = fileno(fp);
ev[n].filter = EVFILT_READ;
ev[n].flags = EV_ADD | EV_ENABLE;
evp[n] = &ev[n];
n++;
if (kevent(kq, n, evp, 0, NULL, &ts) < 0)
err(1, "kevent");
add_events = 0;
}
if (kevent(kq, 0, NULL, 1, ev, NULL) < 0)
err(1, "kevent");
if (ev->filter == EVFILT_VNODE) {
fp = freopen(fname, "r", fp);
if (fp == NULL) {
ierr();
break;
}
add_events = 1;
} else if (ev->data < 0) {
/* file shrank, reposition to end */
if (fseek(fp, 0L, SEEK_END) == -1) {
ierr();
return;
} }
} }
} }