(void)__db_unmap(rp->re_smap, rp->re_msize);
(void)__db_unmapfile(rp->re_smap, rp->re_msize);
__ram_writeback(dbp)	DB *dbp;{	RECNO *rp;	DBT key, data;	db_recno_t keyno;	ssize_t nw;	int fd, ret, t_ret;	u_int8_t delim, *pad;	rp = ((BTREE *)dbp->internal)->bt_recno;	/* If the file wasn't modified, we're done. */	if (!F_ISSET(rp, RECNO_MODIFIED))		return (0);	/* If there's no backing source file, we're done. */	if (rp->re_source == NULL) {		F_CLR(rp, RECNO_MODIFIED);		return (0);	}	/*	 * Read any remaining records into the tree.	 *	 * XXX	 * This is why we can't support transactions when applications specify	 * backing (re_source) files.  At this point we have to read in the	 * rest of the records from the file so that we can write all of the	 * records back out again, which could modify a page for which we'd	 * have to log changes and which we don't have locked.  This could be	 * partially fixed by taking a snapshot of the entire file during the	 * db_open(), or, since db_open() isn't transaction protected, as part	 * of the first DB operation.  But, if a checkpoint occurs then, the	 * part of the log holding the copy of the file could be discarded, and	 * that would make it impossible to recover in the face of disaster.	 * This could all probably be fixed, but it would require transaction	 * protecting the backing source file, i.e. mpool would have to know	 * about it, and we don't want to go there.	 */	if ((ret = __ram_snapshot(dbp)) != 0 && ret != DB_NOTFOUND)		return (ret);	/*	 * !!!	 * Close any underlying mmap region.  This is required for Windows NT	 * (4.0, Service Pack 2) -- if the file is still mapped, the following	 * open will fail.	 */	if (rp->re_smap != NULL) {		(void)__db_unmap(rp->re_smap, rp->re_msize);		rp->re_smap = NULL;	}	/* Get rid of any backing file descriptor, just on GP's. */	if (rp->re_fd != -1) {		(void)__db_close(rp->re_fd);		rp->re_fd = -1;	}	/* Open the file, truncating it. */	if ((ret = __db_open(rp->re_source,	    DB_SEQUENTIAL | DB_TRUNCATE,	    DB_SEQUENTIAL | DB_TRUNCATE, 0, &fd)) != 0) {		__db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret));		return (ret);	}	/*	 * We step through the records, writing each one out.  Use the record	 * number and the dbp->get() function, instead of a cursor, so we find	 * and write out "deleted" or non-existent records.	 */	memset(&key, 0, sizeof(key));	memset(&data, 0, sizeof(data));	key.size = sizeof(db_recno_t);	key.data = &keyno;	/*	 * We'll need the delimiter if we're doing variable-length records,	 * and the pad character if we're doing fixed-length records.	 */	delim = rp->re_delim;	if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {		if ((pad = (u_int8_t *)__db_malloc(rp->re_len)) == NULL) {			ret = ENOMEM;			goto err;		}		memset(pad, rp->re_pad, rp->re_len);	} else		COMPQUIET(pad, NULL);	for (keyno = 1;; ++keyno) {		switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {		case 0:			if ((ret =			    __db_write(fd, data.data, data.size, &nw)) != 0)				goto err;			if (nw != (ssize_t)data.size) {				ret = EIO;				goto err;			}			break;		case DB_KEYEMPTY:			if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {				if ((ret =				    __db_write(fd, pad, rp->re_len, &nw)) != 0)					goto err;				if (nw != (ssize_t)rp->re_len) {					ret = EIO;					goto err;				}			}			break;		case DB_NOTFOUND:			ret = 0;			goto done;		}		if (!F_ISSET(dbp, DB_RE_FIXEDLEN)) {			if ((ret = __db_write(fd, &delim, 1, &nw)) != 0)				goto err;			if (nw != 1) {				ret = EIO;				goto err;			}		}	}err:done:	/* Close the file descriptor. */	if ((t_ret = __db_close(fd)) != 0 || ret == 0)		ret = t_ret;	if (ret == 0)		F_CLR(rp, RECNO_MODIFIED);	return (ret);}