(ef_open): Failed to reset empfile member fd on failure, and leaked

file descriptors.

(ef_flush, ef_close): Rely on negative fd instead of null cache to
detect unopened file.  This is more logical and consistent with the
use of cache by the new tables that are not file-backed (rev. 1.22).
Use CANT_HAPPEN().

(ef_close): Failed to report cash flush failure.

(ef_close): Clear all EFF_OPEN flags.  Should have been done in
rev. 1.27.
This commit is contained in:
Markus Armbruster 2005-10-24 20:18:04 +00:00
parent 1c4fb67911
commit 3eb3607f0d

View file

@ -61,7 +61,7 @@ int
ef_open(int type, int how) ef_open(int type, int how)
{ {
struct empfile *ep; struct empfile *ep;
int oflags, fsiz, size; int oflags, fd, fsiz, size;
if (ef_check(type) < 0) if (ef_check(type) < 0)
return 0; return 0;
@ -78,33 +78,38 @@ ef_open(int type, int how)
#if defined(_WIN32) #if defined(_WIN32)
oflags |= O_BINARY; oflags |= O_BINARY;
#endif #endif
if ((ep->fd = open(ep->file, oflags, 0660)) < 0) { if ((fd = open(ep->file, oflags, 0660)) < 0) {
logerror("%s: open failed", ep->file); logerror("Can't open %s (%s)", ep->file, strerror(errno));
return 0;
}
fsiz = fsize(fd);
if (fsiz % ep->size) {
logerror("Can't open %s (file size not a multiple of record size %d)",
ep->file, ep->size);
close(fd);
return 0;
}
ep->fids = fsiz / ep->size;
if (how & EFF_MEM)
ep->csize = ep->fids;
else
ep->csize = max(1, blksize(fd) / ep->size);
size = ep->csize * ep->size;
ep->cache = malloc(size);
if (ep->cache == NULL) {
logerror("Can't open %s: out of memory", ep->file);
close(fd);
return 0; return 0;
} }
ep->baseid = 0; ep->baseid = 0;
ep->cids = 0; ep->cids = 0;
ep->flags = (ep->flags & ~EFF_OPEN) | (how ^ ~EFF_CREATE); ep->flags = (ep->flags & ~EFF_OPEN) | (how ^ ~EFF_CREATE);
fsiz = fsize(ep->fd); ep->fd = fd;
if (fsiz % ep->size) { if (how & EFF_MEM) {
logerror("Can't open %s (file size not a multiple of record size %d)",
ep->file, ep->size);
close(ep->fd);
return 0;
}
ep->fids = fsiz / ep->size;
if (ep->flags & EFF_MEM)
ep->csize = ep->fids;
else
ep->csize = max(1, blksize(ep->fd) / ep->size);
size = ep->csize * ep->size;
ep->cache = malloc(size);
if (ep->cache == NULL) {
logerror("ef_open: %s malloc(%d) failed\n", ep->file, size);
return 0;
}
if (ep->flags & EFF_MEM) {
if (fillcache(ep, 0) != ep->fids) { if (fillcache(ep, 0) != ep->fids) {
ep->cids = 0; /* prevent cache flush */
ep->flags &= ~EFF_OPEN; /* maintain invariant */
ef_close(type);
return 0; return 0;
} }
} }
@ -119,24 +124,19 @@ int
ef_close(int type) ef_close(int type)
{ {
struct empfile *ep; struct empfile *ep;
int r; int retval;
if (ef_check(type) < 0) retval = ef_flush(type);
return 0;
ep = &empfile[type]; ep = &empfile[type];
if (ep->cache == NULL) { ep->flags &= ~EFF_OPEN;
/* no cache implies never opened */
return 0;
}
ef_flush(type);
ep->flags &= ~EFF_MEM;
free(ep->cache); free(ep->cache);
ep->cache = NULL; ep->cache = NULL;
if ((r = close(ep->fd)) < 0) { if (close(ep->fd) < 0) {
logerror("ef_close: %s close(%d) -> %d", ep->name, ep->fd, r); logerror("Error closing %s (%s)", ep->name, strerror(errno));
retval = 0;
} }
ep->fd = -1; ep->fd = -1;
return 1; return retval;
} }
/* /*
@ -150,10 +150,8 @@ ef_flush(int type)
if (ef_check(type) < 0) if (ef_check(type) < 0)
return 0; return 0;
ep = &empfile[type]; ep = &empfile[type];
if (ep->cache == NULL) { if (CANT_HAPPEN(ep->fd < 0))
/* no cache implies never opened */
return 0; return 0;
}
/* /*
* We don't know which cache entries are dirty. ef_write() writes * We don't know which cache entries are dirty. ef_write() writes
* through, but direct updates through ef_ptr() don't. They are * through, but direct updates through ef_ptr() don't. They are