timeout

Nikola Vladov <[email protected]> 8 Apr 2006 19:11:10 -0000
Newsgroups gmane.comp.web.fnord
Message-ID <[email protected]>
I I modified fnord to use timeout.  next part must be before
int main(...)  The first line after main(...) in my code is

  buffer_1->op = timeoutfrite;

Enjoy,  Nikola


int timeoutwrite(int fd,char *buf,int len) {
  time_t now, deadline;
  struct pollfd x;
  now = time(0);
  deadline = now + WRITETIMEOUT;
  x.fd = fd;
  x.events = POLLOUT;
  for (;;) {
    if (deadline<=now) {
      errno = ETIMEDOUT;
      return -1;
    }
    x.revents=0;
    if (poll(&x,1,(deadline-now)*1000)==1 &&
	(x.revents & POLLOUT)) return write(fd,buf,len);
    time(&now);
  }
}

extern int buffer_stubborn(int (*op)(),int fd,const char* buf, unsigned int len);

static int serve_read_write(int fd) {
  off_t todo = rangeend-rangestart;
  off_t buf_len = buffer_1->a;
  if (rangestart) lseek(fd,rangestart,SEEK_SET);
  while (todo>0) {
    int len = read(fd, buffer_1->x, todo > buf_len ? buf_len : todo);
    if (len==-1) return 1;
    todo -= len;
    if (buffer_stubborn(timeoutwrite, 1, buffer_1->x, len))
      return -1;
  }
  return 0;
}

#ifdef USE_MMAP
static int serve_mmap(int fd) {
  off_t mapstart,maplen;
  unsigned long mapofs;
  char* map;
  mapstart=rangestart&(~(off_t)0xfff); /* round down to 4k page */
  maplen=rangeend-mapstart;
  mapofs=rangestart-mapstart;
  if (maplen>64*1024*1024) maplen=64*1024*1024;
  map=mmap(0,maplen,PROT_READ,MAP_PRIVATE,fd,mapstart);
  if (map==MAP_FAILED) {
    if (errno==EINVAL && mapstart) {
      /* try rounded to 64k pages */
      mapstart=rangestart&0xffff;
      maplen=rangeend-mapstart;
      mapofs=rangestart-mapstart;
      map=mmap(0,maplen,PROT_READ,MAP_PRIVATE,fd,mapstart);
      if (map==MAP_FAILED)
	/* didn't work, use read/write instead. */
	return serve_read_write(fd);
    } else return serve_read_write(fd);
  }
  while (rangestart<rangeend) {
    if (buffer_stubborn(timeoutwrite,1,map+mapofs,(int)(maplen-mapofs)))
      return -1;
    rangestart+=maplen-mapofs;
    mapstart+=maplen;
    munmap(map,maplen); mapofs=0;
    maplen=rangeend-mapstart;
    if (maplen) {
      if (maplen>64*1024*1024) maplen=64*1024*1024;
      map=mmap(0,maplen,PROT_READ,MAP_SHARED,fd,mapstart);
      if (map==MAP_FAILED)
	/* can't happen, really */
	return serve_read_write(fd);
    }
  }
  return 0;
}
#endif
 
#ifdef USE_MMAP
#define SERVE_FILE serve_mmap
#else
#define SERVE_FILE serve_read_write
#endif

/* write from offset "rangestart" to offset "rangeend" to fd #1 */
static int serve_static_data(int fd) {
#ifdef TCP_CORK
  {
    int one=1;
    setsockopt(1,IPPROTO_TCP,TCP_CORK,&one,sizeof(one));
    corked=1;
  }
#endif
  if (buffer_flush(buffer_1)) return -1;
#ifdef USE_SENDFILE
  /* for small files, sendfile is actually slower */
  if (rangeend-rangestart < 4096) return serve_read_write(fd);
  {
    off_t offset=rangestart, l=rangeend-rangestart, c, w;
    while (l) {
      c=(l>(1ul<<31))?1ul<<31:l;
      if ((w=sendfile(1,fd,&offset,c))==-1) {
	rangestart = offset;
	return SERVE_FILE(fd);
      }
      l-=w;
    }
    return 0;
  }
#else
  return SERVE_FILE(fd);
#endif
}