diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-11-08 22:10:03 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-11-08 22:10:03 +0000 |
commit | 3908473c809d5c24940faebfabdad673f4302178 (patch) | |
tree | 6a1989499ee61771c7764afd2b24d12ebd25b8fb /src/backend/storage/smgr/md.c | |
parent | ebe0b236909732c75d665c73363bd4ac7a7aa138 (diff) | |
download | postgresql-3908473c809d5c24940faebfabdad673f4302178.tar.gz postgresql-3908473c809d5c24940faebfabdad673f4302178.zip |
Make DROP TABLE rollback-able: postpone physical file delete until commit.
(WAL logging for this is not done yet, however.) Clean up a number of really
crufty things that are no longer needed now that DROP behaves nicely. Make
temp table mapper do the right things when drop or rename affecting a temp
table is rolled back. Also, remove "relation modified while in use" error
check, in favor of locking tables at first reference and holding that lock
throughout the statement.
Diffstat (limited to 'src/backend/storage/smgr/md.c')
-rw-r--r-- | src/backend/storage/smgr/md.c | 162 |
1 files changed, 62 insertions, 100 deletions
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index da466afe9f8..c97a46ba4b4 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -8,17 +8,17 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.77 2000/10/28 16:20:57 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.78 2000/11/08 22:10:00 tgl Exp $ * *------------------------------------------------------------------------- */ +#include "postgres.h" + #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <sys/file.h> -#include "postgres.h" - #include "catalog/catalog.h" #include "miscadmin.h" #include "storage/smgr.h" @@ -123,63 +123,39 @@ mdinit() int mdcreate(Relation reln) { + char *path; int fd, vfd; - char *path; - Assert(reln->rd_unlinked && reln->rd_fd < 0); + Assert(reln->rd_fd < 0); path = relpath(reln->rd_node); - fd = FileNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, 0600); - /* - * For cataloged relations, pg_class is guaranteed to have a unique - * record with the same relname by the unique index. So we are able to - * reuse existent files for new cataloged relations. Currently we reuse - * them in the following cases. 1. they are empty. 2. they are used - * for Index relations and their size == BLCKSZ * 2. - * - * During bootstrap processing, we skip that check, because pg_time, - * pg_variable, and pg_log get created before their .bki file entries - * are processed. - */ + fd = FileNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, 0600); if (fd < 0) { int save_errno = errno; - if (!IsBootstrapProcessingMode() && - reln->rd_rel->relkind == RELKIND_UNCATALOGED) - return -1; - - fd = FileNameOpenFile(path, O_RDWR | PG_BINARY, 0600); + /* + * During bootstrap, there are cases where a system relation will be + * accessed (by internal backend processes) before the bootstrap + * script nominally creates it. Therefore, allow the file to exist + * already, but in bootstrap mode only. (See also mdopen) + */ + if (IsBootstrapProcessingMode()) + fd = FileNameOpenFile(path, O_RDWR | PG_BINARY, 0600); if (fd < 0) { + pfree(path); /* be sure to return the error reported by create, not open */ errno = save_errno; return -1; } - if (!IsBootstrapProcessingMode()) - { - bool reuse = false; - long len = FileSeek(fd, 0L, SEEK_END); - - if (len == 0) - reuse = true; - else if (reln->rd_rel->relkind == RELKIND_INDEX && - len == BLCKSZ * 2) - reuse = true; - if (!reuse) - { - FileClose(fd); - /* be sure to return the error reported by create */ - errno = save_errno; - return -1; - } - } errno = 0; } - reln->rd_unlinked = false; + + pfree(path); vfd = _fdvec_alloc(); if (vfd < 0) @@ -187,12 +163,10 @@ mdcreate(Relation reln) Md_fdvec[vfd].mdfd_vfd = fd; Md_fdvec[vfd].mdfd_flags = (uint16) 0; + Md_fdvec[vfd].mdfd_lstbcnt = 0; #ifndef LET_OS_MANAGE_FILESIZE Md_fdvec[vfd].mdfd_chain = (MdfdVec *) NULL; #endif - Md_fdvec[vfd].mdfd_lstbcnt = 0; - - pfree(path); return vfd; } @@ -201,65 +175,50 @@ mdcreate(Relation reln) * mdunlink() -- Unlink a relation. */ int -mdunlink(Relation reln) +mdunlink(RelFileNode rnode) { - int nblocks; - int fd; - MdfdVec *v; - - /* - * If the relation is already unlinked,we have nothing to do any more. - */ - if (reln->rd_unlinked && reln->rd_fd < 0) - return SM_SUCCESS; - - /* - * Force all segments of the relation to be opened, so that we won't - * miss deleting any of them. - */ - nblocks = mdnblocks(reln); + int status = SM_SUCCESS; + int save_errno = 0; + char *path; - /* - * Clean out the mdfd vector, letting fd.c unlink the physical files. - * - * NOTE: We truncate the file(s) before deleting 'em, because if other - * backends are holding the files open, the unlink will fail on some - * platforms (think Microsoft). Better a zero-size file gets left - * around than a big file. Those other backends will be forced to - * close the relation by cache invalidation, but that probably hasn't - * happened yet. - */ - fd = RelationGetFile(reln); - if (fd < 0) /* should not happen */ - elog(ERROR, "mdunlink: mdnblocks didn't open relation"); + path = relpath(rnode); - Md_fdvec[fd].mdfd_flags = (uint16) 0; + /* Delete the first segment, or only segment if not doing segmenting */ + if (unlink(path) < 0) + { + status = SM_FAIL; + save_errno = errno; + } #ifndef LET_OS_MANAGE_FILESIZE - for (v = &Md_fdvec[fd]; v != (MdfdVec *) NULL;) + /* Get the additional segments, if any */ + if (status == SM_SUCCESS) { - MdfdVec *ov = v; + char *segpath = (char *) palloc(strlen(path) + 12); + int segno; - FileTruncate(v->mdfd_vfd, 0); - FileUnlink(v->mdfd_vfd); - v = v->mdfd_chain; - if (ov != &Md_fdvec[fd]) - pfree(ov); + for (segno = 1; ; segno++) + { + sprintf(segpath, "%s.%d", path, segno); + if (unlink(segpath) < 0) + { + /* ENOENT is expected after the last segment... */ + if (errno != ENOENT) + { + status = SM_FAIL; + save_errno = errno; + } + break; + } + } + pfree(segpath); } - Md_fdvec[fd].mdfd_chain = (MdfdVec *) NULL; -#else - v = &Md_fdvec[fd]; - FileTruncate(v->mdfd_vfd, 0); - FileUnlink(v->mdfd_vfd); #endif - _fdvec_free(fd); - - /* be sure to mark relation closed && unlinked */ - reln->rd_fd = -1; - reln->rd_unlinked = true; + pfree(path); - return SM_SUCCESS; + errno = save_errno; + return status; } /* @@ -327,24 +286,29 @@ mdopen(Relation reln) int vfd; Assert(reln->rd_fd < 0); + path = relpath(reln->rd_node); fd = FileNameOpenFile(path, O_RDWR | PG_BINARY, 0600); + if (fd < 0) { - /* in bootstrap mode, accept mdopen as substitute for mdcreate */ + /* + * During bootstrap, there are cases where a system relation will be + * accessed (by internal backend processes) before the bootstrap + * script nominally creates it. Therefore, accept mdopen() as a + * substitute for mdcreate() in bootstrap mode only. (See mdcreate) + */ if (IsBootstrapProcessingMode()) fd = FileNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, 0600); if (fd < 0) { - elog(NOTICE, "mdopen: couldn't open %s: %m", path); - /* mark relation closed and unlinked */ - reln->rd_fd = -1; - reln->rd_unlinked = true; + pfree(path); return -1; } } - reln->rd_unlinked = false; + + pfree(path); vfd = _fdvec_alloc(); if (vfd < 0) @@ -362,8 +326,6 @@ mdopen(Relation reln) #endif #endif - pfree(path); - return vfd; } |