(do_write): New.

(ef_flush, ef_write): Use it.  Old code couldn't cope with interrupted
or short writes (mostly harmless, as disk reads commonly complete).

(ef_write): Use CANT_HAPPEN() for catching unimplemented table
extensions.
This commit is contained in:
Markus Armbruster 2005-10-24 19:17:05 +00:00
parent ab03d83ce1
commit 1c4fb67911

View file

@ -47,7 +47,9 @@
#include "gen.h" #include "gen.h"
static int fillcache(struct empfile *ep, int start); static int fillcache(struct empfile *, int);
static int do_write(struct empfile *, void *, int, int);
/* /*
* Open the binary file for table TYPE (EF_SECTOR, ...). * Open the binary file for table TYPE (EF_SECTOR, ...).
@ -144,8 +146,6 @@ int
ef_flush(int type) ef_flush(int type)
{ {
struct empfile *ep; struct empfile *ep;
int size;
int r;
if (ef_check(type) < 0) if (ef_check(type) < 0)
return 0; return 0;
@ -160,19 +160,9 @@ ef_flush(int type)
* allowed only with EFF_MEM. Assume the whole cash is dirty * allowed only with EFF_MEM. Assume the whole cash is dirty
* then. * then.
*/ */
if (!(ep->flags & EFF_RDONLY) && (ep->flags & EFF_MEM)) { if (!(ep->flags & EFF_RDONLY) && (ep->flags & EFF_MEM))
size = ep->csize * ep->size; return do_write(ep, ep->cache, ep->baseid, ep->cids) >= 0;
if ((r = lseek(ep->fd, 0L, SEEK_SET)) < 0) {
logerror("ef_flush: %s cache lseek(%d, 0L, SEEK_SET) -> %d",
ep->name, ep->fd, r);
return 0;
}
if (write(ep->fd, ep->cache, size) != size) {
logerror("ef_flush: %s cache write(%d, %p, %d) -> %d",
ep->name, ep->fd, ep->cache, ep->size, r);
return 0;
}
}
return 1; return 1;
} }
@ -277,6 +267,42 @@ fillcache(struct empfile *ep, int start)
return ep->cids; return ep->cids;
} }
/*
* Write COUNT elements from BUF to EP, starting at ID.
* Return 0 on success, -1 on error.
*/
static int
do_write(struct empfile *ep, void *buf, int id, int count)
{
int n, ret;
char *p;
if (CANT_HAPPEN(ep->fd < 0 || id < 0 || count < 0))
return -1;
if (lseek(ep->fd, id * ep->size, SEEK_SET) == (off_t)-1) {
logerror("Error seeking %s (%s)", ep->file, strerror(errno));
return -1;
}
p = buf;
n = count * ep->size;
while (n > 0) {
ret = write(ep->fd, p, n);
if (ret < 0) {
if (errno != EAGAIN) {
logerror("Error writing %s (%s)", ep->file, strerror(errno));
return -1;
}
} else {
p += ret;
n -= ret;
}
}
return 0;
}
/* /*
* buffered write. Modifies read cache (if applicable) * buffered write. Modifies read cache (if applicable)
* and writes through to disk. * and writes through to disk.
@ -284,7 +310,6 @@ fillcache(struct empfile *ep, int start)
int int
ef_write(int type, int id, void *from) ef_write(int type, int id, void *from)
{ {
int r;
struct empfile *ep; struct empfile *ep;
char *to; char *to;
@ -296,18 +321,12 @@ ef_write(int type, int id, void *from)
logerror("ef_write: type %d id %d is too large!\n", type, id); logerror("ef_write: type %d id %d is too large!\n", type, id);
return 0; return 0;
} }
if ((r = lseek(ep->fd, id * ep->size, SEEK_SET)) < 0) {
logerror("ef_write: %s #%d lseek(%d, %d, SEEK_SET) -> %d",
ep->name, id, ep->fd, id * ep->size, r);
return 0;
}
if (ep->prewrite) if (ep->prewrite)
ep->prewrite(id, from); ep->prewrite(id, from);
if ((r = write(ep->fd, from, ep->size)) != ep->size) { if (CANT_HAPPEN((ep->flags & EFF_MEM) ? id >= ep->fids : id > ep->fids))
logerror("ef_write: %s #%d write(%d, %p, %d) -> %d", return 0; /* not implemented */
ep->name, id, ep->fd, from, ep->size, r); if (do_write(ep, from, id, 1) < 0)
return 0; return 0;
}
if (id >= ep->baseid && id < ep->baseid + ep->cids) { if (id >= ep->baseid && id < ep->baseid + ep->cids) {
/* update the cache if necessary */ /* update the cache if necessary */
to = ep->cache + (id - ep->baseid) * ep->size; to = ep->cache + (id - ep->baseid) * ep->size;
@ -315,13 +334,8 @@ ef_write(int type, int id, void *from)
} }
CANT_HAPPEN(id > ep->fids); CANT_HAPPEN(id > ep->fids);
if (id >= ep->fids) { if (id >= ep->fids) {
if (ep->flags & EFF_MEM) { /* write beyond end of file extends it, take note */
logerror("file %s went beyond %d items; won't be able toread item w/o restart", ep->fids = id + 1;
ep->name, ep->fids);
} else {
/* write expanded file; ep->fids = last id + 1 */
ep->fids = id + 1;
}
} }
return 1; return 1;
} }