9front - general discussion about 9front
 help / color / mirror / Atom feed
* cwfs partial line
@ 2018-11-14 19:11 Joe M
  0 siblings, 0 replies; only message in thread
From: Joe M @ 2018-11-14 19:11 UTC (permalink / raw)
  To: 9front

Hello,

When I stream some data through a cwfs file, I am noticing partial
line's (if the line is '12345 6879\n', it would come through as
'12345 6\n' and then '879\n').

These are the symptoms I noticed with this behaviour:

1. When the downstream reader is using bio's Brdstr or Brdline, the
issue still occurs.

2. When there are multiple programs reading from the same file, all of
them except 1 showed this partial line (I error out when such partial
line comes through).

3. I am reading the file with an interval of 100ms (modified tail to
read with smaller intervals between loops). I am attaching my version
of tail. It is a plain read + write.

4. I also noticed the same error when I have an rc read loop of the
file.

5. The file contents have no partial lines when I open the file with
acme when I check it out after the error was reported.

The above observations make me suspect that the issue is cwfs related
and not with bio or how the file is read. Given that it happened for
multiple processes, I suspect it would be somewhere in getbuf while
appending to a file (uninitialized buffer?).

I am new to cwfs and am slowly working through the docs and code.

I want to check if anyone has noticed such behaviour or any
suggestions that can help debug this issue.

Thanks


my modified tail

#include <u.h>
#include <libc.h>

/*
similar to tail, but for:
	sleep interval is a parameter
if the file size is reduced, then it starts from the beginning
if the file is replaced, it follows the new file
./6.tailf /tmp/test.txt
mv /tmp/test.txt /tmp/test.txt.0; echo "testing again" >/tmp/test.txt
 */

enum {
	BufSize = 1 * 1024 * 1024 * sizeof(uchar),
	Interval = 100,
	Len = 256,
};

int stop = 0;
int handler(void *, char *msg);

void
usage(void)
{
	fprint(2,
	       "usage: %s [-i <sleep interval>] [-s <seek offset>] file\n",
	       argv0);
	fprint(2,
	       "\t-i <sleep interval>: sleep interval in milliseconds, default is 100 milliseconds\n");
	fprint(2,
	       "\t-s <seek offset>: seek to this offset from the beginning of the file. seeking in a pipe is a no-op.\n");
	exits("usage");
}

void
main(int argc, char **argv)
{
	int interval = Interval, seektype = 2, loop = 1;
	vlong seekoffset = 0LL;
	int fd, n, w;
	uchar *buf;
	char *filename, filepathname[Len];
	Dir *old, *new;

	ARGBEGIN {
case 'i':                      /* sleep interval */
		interval = atol(EARGF(usage()));
		break;
case 's':                      /* seek offset from start */
		seektype = 0;
		seekoffset = atol(EARGF(usage()));
		break;
default:
		usage();
	}
	ARGEND;

	if(argc != 1) {
		fprint(2, "%s: mandatory argument filename not provided\n",
		       argv0);
		usage();
	}

	if(strlen(argv[0]) >= Len)
		sysfatal
		    ("%s: file name length should be increased from %d to %ld",
		     argv0, Len, strlen(argv[0]) + 1);
	strncpy(filepathname, argv[0], Len);
	if((filename = strrchr(filepathname, '/')) == 0)
		filename = filepathname;
	else
		filename++;
	if((fd = open(filepathname, OREAD)) < 0)
		sysfatal("cannot open file %s: %r", filepathname);

	if((buf = mallocz(BufSize, 1)) == nil)
		sysfatal("%s: malloc of %d bytes failed: %r", argv0,
			 BufSize);

	atnotify(handler, 1);
	old = dirfstat(fd);
	seek(fd, seekoffset, seektype);
	while(loop == 1) {
		/* read once after the stop is received */
		loop = stop == 1 ? 0 : 1;

		/* BUG: if the file contents are replaced but the new
		   contents are more than the old contents, then this does
		   not seek back to the beginning. not fixing this as it is
		   very unlikely. To fix this, would mean we would have to
		   compare the file contents every time that the file length
		   has increased and that is an expensive operation */
		new = dirfstat(fd);
		if(new->length < old->length
		   || (new->length == old->length
		       && new->mtime > old->mtime)) {
			fprint(2,
			       "%s: old->length=%lld, old->mtime=%lud,"
			       " new->length=%lld, new->mtime=%lud"
			       " seeking back to 0\n", argv0, old->length,
			       old->mtime, new->length, new->mtime);
			seek(fd, 0LL, 0);
		}
		free(old);
		old = new;

		if(strlen(filename) != strlen(new->name)
		   || strncmp(filename, new->name, strlen(filename)) != 0) {
			close(fd);
			fprint(2,
			       "%s,filename changed: filename=%s, new->name=%s, waiting for the new file\n",
			       argv0, filename, new->name);
			/* old file has been renamed, new file with this
			   name has not been created yet */
			while(loop == 1
			      && (new = dirstat(filepathname)) == nil)
				sleep(interval > 0 ? interval : Interval);

			if(loop == 0)
				goto end;
			fprint(2,
			       "%s: file replaced: filename=%s, new->name=%s\n",
			       argv0, filename, new->name);
			if((fd = open(filepathname, OREAD)) < 0)
				sysfatal("cannot open file %s: %r",
					 filepathname);
			free(old);
			old = new;
		}
		while((n = read(fd, buf, BufSize)) > 0) {
			if((w = write(1, buf, n)) != n) {
				sysfatal
				    ("%s: could only write %d of %d bytes: %r\n",
				     argv0, w, n);
			}
		}
		if(stop == 0 && n == 0)
			sleep(interval > 0 ? interval : Interval);
	}
	close(fd);
      end:
	free(buf);
	exits(nil);
}

int
handler(void *, char *msg)
{
	if(strncmp(msg, "stop", 4) == 0 || strncmp(msg, "stop\n", 5) == 0) {
		stop = 1;
		return 1;
	}
	return 0;
}



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2018-11-14 19:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-14 19:11 cwfs partial line Joe M

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).