From dffb673692f96a6cc52411762b8ba07201687313 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Fri, 25 May 2001 15:34:50 +0000 Subject: [PATCH] While changing Cygwin Python to build its core as a DLL (like Win32 Python) to support shared extension modules, I have learned that Guido prefers the style of the attached patch to solve the above problem. I feel that this solution is particularly appropriate in this case because the following: PglargeType PgType PgQueryType are already being handled in the way that I am proposing for PgSourceType. Jason Tishler --- doc/src/sgml/ref/vacuum.sgml | 5 +- src/backend/access/transam/varsup.c | 46 +++++++++++++++- src/backend/commands/vacuum.c | 82 ++++++++++++++++++++++++++++- src/backend/postmaster/postmaster.c | 55 ++++++++++++++++++- src/backend/storage/file/fd.c | 20 ++++--- src/backend/storage/lmgr/proc.c | 3 +- src/include/access/transam.h | 3 +- src/include/storage/fd.h | 4 +- src/include/storage/proc.h | 5 +- src/interfaces/python/pgmodule.c | 7 +-- 10 files changed, 210 insertions(+), 20 deletions(-) diff --git a/doc/src/sgml/ref/vacuum.sgml b/doc/src/sgml/ref/vacuum.sgml index cbb182466e..0722b8068d 100644 --- a/doc/src/sgml/ref/vacuum.sgml +++ b/doc/src/sgml/ref/vacuum.sgml @@ -1,5 +1,5 @@ @@ -154,7 +154,8 @@ NOTICE: Index index: Pages 28; With no parameter, VACUUM processes every table in the - current database. With a parameter, VACUUM processes + current database. It also detects any extraneous files in the + database directory. With a parameter, VACUUM processes only that table. diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index 34c607eab9..95547bbe83 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -6,7 +6,7 @@ * Copyright (c) 2000, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.38 2001/03/22 03:59:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.39 2001/05/25 15:34:49 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,7 +16,10 @@ #include "access/transam.h" #include "access/xlog.h" #include "storage/proc.h" +#include "storage/sinval.h" +#include "storage/sinvaladt.h" +extern SISeg *shmInvalBuffer; /* Number of XIDs and OIDs to prefetch (preallocate) per XLOG write */ #define VAR_XID_PREFETCH 1024 @@ -143,3 +146,44 @@ CheckMaxObjectId(Oid assigned_oid) SpinRelease(OidGenLockId); } + +/* + * GetMinBackendOid -- returns lowest oid stored on startup of + * each backend. + */ +Oid +GetMinStartupOid(void) +{ + SISeg *segP = shmInvalBuffer; + ProcState *stateP = segP->procState; + int index; + Oid min_oid; + + /* prime with current oid, no need for lock */ + min_oid = ShmemVariableCache->nextOid; + + SpinAcquire(SInvalLock); + + for (index = 0; index < segP->lastBackend; index++) + { + SHMEM_OFFSET pOffset = stateP[index].procStruct; + + if (pOffset != INVALID_OFFSET) + { + PROC *proc = (PROC *) MAKE_PTR(pOffset); + Oid proc_oid; + + proc_oid = proc->startOid; /* we don't use spin-locking in + * AbortTransaction() ! */ + if (proc == MyProc || proc_oid <= BootstrapObjectIdData) + continue; + if (proc_oid < min_oid) + min_oid = proc_oid; + } + } + + SpinRelease(SInvalLock); + return min_oid; +} + + diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 8ec2bd07fd..e6bdc3a3f2 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.193 2001/05/18 21:24:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.194 2001/05/25 15:34:49 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,9 +16,12 @@ #include #include +#include +#include #include #include #include +#include #include #include @@ -30,6 +33,7 @@ #include "access/genam.h" #include "access/heapam.h" +#include "access/transam.h" #include "access/xlog.h" #include "catalog/catalog.h" #include "catalog/catname.h" @@ -159,6 +163,7 @@ static int vac_cmp_vtlinks(const void *left, const void *right); static bool enough_space(VacPage vacpage, Size len); static void init_rusage(VacRUsage *ru0); static char *show_rusage(VacRUsage *ru0); +static void report_orphans(void); /* @@ -236,6 +241,10 @@ vacuum(VacuumStmt *vacstmt) /* clean up */ vacuum_shutdown(); + + if (VacRelName == NULL) + report_orphans(); + } /* @@ -2646,3 +2655,74 @@ show_rusage(VacRUsage *ru0) return result; } + +/* + * report_orphans + * + * Report files that are not referenced by any pg_class.relfilenode. + * Could be caused by backend crash no cleaning up. + */ +static void +report_orphans(void) +{ + DIR *db_dir; + struct dirent *db_de; + Relation rel; + TupleDesc tupdesc; + HeapScanDesc scan; + HeapTuple tuple; + Oid dir_file_oid; + Oid rel_file_oid; + Datum d; + bool n; + bool match_found; + char cwd[MAXPGPATH]; + + getcwd(cwd,MAXPGPATH); + db_dir = opendir("."); + rel = heap_openr(RelationRelationName, AccessShareLock); + Assert(db_dir); + + /* + * Cycle through directory and check each file against + * pg_class.relfilenode. + * XXX This is O(n^2). Is it too slow? bjm + */ + while ((db_de = readdir(db_dir)) != NULL) + { + if (strspn(db_de->d_name, "0123456789") == + strlen(db_de->d_name)) + { + dir_file_oid = (Oid) strtoul((db_de->d_name), NULL, 10); + + if (dir_file_oid >= GetMinStartupOid() || + dir_file_oid <= BootstrapObjectIdData) + continue; + + tupdesc = RelationGetDescr(rel); + + match_found = false; + scan = heap_beginscan(rel, false, SnapshotNow, 0, (ScanKey) NULL); + while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) + { + d = heap_getattr(tuple, Anum_pg_class_relfilenode, tupdesc, &n); + rel_file_oid = DatumGetObjectId(d); + if (dir_file_oid == rel_file_oid) + { + match_found = true; + break; + } + } + heap_endscan(scan); + /* make sure there was no oid wrap-around during the scan */ + if (!match_found && dir_file_oid <= ShmemVariableCache->nextOid) + elog(NOTICE, + "Unreferenced file found in database directory:\n\t%s/%s", + cwd, db_de->d_name); + /* Maybe one day we can unlink too. bjm 2001-05-24 */ + } + } + + heap_close(rel, AccessShareLock); + closedir(db_dir); +} diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index f6b8884dcc..dc6ee27fa0 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -28,7 +28,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.212 2001/04/19 19:09:23 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.213 2001/05/25 15:34:50 momjian Exp $ * * NOTES * @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -243,6 +244,7 @@ static void RandomSalt(char *salt); static void SignalChildren(int signal); static int CountChildren(void); static bool CreateOptsFile(int argc, char *argv[]); +static void RemovePgSorttemp(void); static pid_t SSDataBase(int xlop); @@ -595,6 +597,9 @@ PostmasterMain(int argc, char *argv[]) if (!CreateDataDirLockFile(DataDir, true)) ExitPostmaster(1); + /* Remove old sort files */ + RemovePgSorttemp(); + /* * Establish input sockets. */ @@ -2450,3 +2455,51 @@ CreateOptsFile(int argc, char *argv[]) fclose(fp); return true; } + + +/* + * Remove old sort files + */ +static void +RemovePgSorttemp(void) +{ + char db_path[MAXPGPATH]; + char temp_path[MAXPGPATH]; + char rm_path[MAXPGPATH]; + DIR *db_dir; + DIR *temp_dir; + struct dirent *db_de; + struct dirent *temp_de; + + /* + * Cycle through pg_tempsort for all databases and + * and remove old sort files. + */ + /* trailing slash forces symlink following */ + snprintf(db_path, sizeof(db_path), "%s/base/", DataDir); + if ((db_dir = opendir(db_path)) != NULL) + { + while ((db_de = readdir(db_dir)) != NULL) + { + snprintf(temp_path, sizeof(temp_path), + "%s/%s/%s/", db_path, db_de->d_name, SORT_TEMP_DIR); + if ((temp_dir = opendir(temp_path)) != NULL) + { + while ((temp_de = readdir(temp_dir)) != NULL) + { + if (strspn(temp_de->d_name, "0123456789.") == + strlen(temp_de->d_name)) + { + snprintf(rm_path, sizeof(temp_path), + "%s/%s/%s/%s", + db_path, db_de->d_name, + SORT_TEMP_DIR, temp_de->d_name); + unlink(rm_path); + } + } + closedir(temp_dir); + } + } + closedir(db_dir); + } +} diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 27e53f41c8..8816589787 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.76 2001/04/03 04:07:02 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.77 2001/05/25 15:34:50 momjian Exp $ * * NOTES: * @@ -742,21 +742,29 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode) File OpenTemporaryFile(void) { - char tempfilename[64]; + char tempfilepath[128]; File file; /* * Generate a tempfile name that's unique within the current * transaction */ - snprintf(tempfilename, sizeof(tempfilename), - "pg_sorttemp%d.%ld", MyProcPid, tempFileCounter++); + snprintf(tempfilepath, sizeof(tempfilepath), + "%s%c%d.%ld", SORT_TEMP_DIR, SEP_CHAR, MyProcPid, + tempFileCounter++); /* Open the file */ - file = FileNameOpenFile(tempfilename, + file = FileNameOpenFile(tempfilepath, O_RDWR | O_CREAT | O_TRUNC | PG_BINARY, 0600); if (file <= 0) - elog(ERROR, "Failed to create temporary file %s", tempfilename); + { + /* mkdir could fail if some one else already created it */ + mkdir(SORT_TEMP_DIR, S_IRWXU); + file = FileNameOpenFile(tempfilepath, + O_RDWR | O_CREAT | O_TRUNC | PG_BINARY, 0600); + if (file <= 0) + elog(ERROR, "Failed to create temporary file %s", tempfilepath); + } /* Mark it for deletion at close or EOXact */ VfdCache[file].fdstate |= FD_TEMPORARY; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index a12d0aa20f..9e9ef04d2c 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.100 2001/03/22 06:16:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.101 2001/05/25 15:34:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -261,6 +261,7 @@ InitProcess(void) MyProc->databaseId = MyDatabaseId; MyProc->xid = InvalidTransactionId; MyProc->xmin = InvalidTransactionId; + MyProc->startOid = ShmemVariableCache->nextOid; MyProc->waitLock = NULL; MyProc->waitHolder = NULL; SHMQueueInit(&(MyProc->procHolders)); diff --git a/src/include/access/transam.h b/src/include/access/transam.h index b18f26b951..6278665345 100644 --- a/src/include/access/transam.h +++ b/src/include/access/transam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: transam.h,v 1.33 2001/05/14 20:30:21 momjian Exp $ + * $Id: transam.h,v 1.34 2001/05/25 15:34:50 momjian Exp $ * * NOTES * Transaction System Version 101 now support proper oid @@ -133,6 +133,7 @@ extern void GetNewTransactionId(TransactionId *xid); extern void ReadNewTransactionId(TransactionId *xid); extern void GetNewObjectId(Oid *oid_return); extern void CheckMaxObjectId(Oid assigned_oid); +extern Oid GetMinStartupOid(void); /* ---------------- * global variable extern declarations diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index 46ec1fdb94..d1867bd610 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: fd.h,v 1.27 2001/02/18 04:39:42 tgl Exp $ + * $Id: fd.h,v 1.28 2001/05/25 15:34:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -39,6 +39,8 @@ * FileSeek uses the standard UNIX lseek(2) flags. */ +#define SORT_TEMP_DIR "pg_sorttemp" + typedef char *FileName; typedef int File; diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 72e2aafd42..ae1fb9f1c0 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: proc.h,v 1.41 2001/03/22 04:01:08 momjian Exp $ + * $Id: proc.h,v 1.42 2001/05/25 15:34:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -50,6 +50,9 @@ struct proc * were starting our xact: vacuum must not * remove tuples deleted by xid >= xmin ! */ + Oid startOid; /* oid at startup, used by vacuum to find + * orphaned files. + */ /* * XLOG location of first XLOG record written by this backend's * current transaction. If backend is not in a transaction or hasn't diff --git a/src/interfaces/python/pgmodule.c b/src/interfaces/python/pgmodule.c index a1ce3cd33f..9cfcd40e53 100644 --- a/src/interfaces/python/pgmodule.c +++ b/src/interfaces/python/pgmodule.c @@ -947,11 +947,7 @@ pgsource_print(pgsourceobject * self, FILE *fp, int flags) /* query type definition */ staticforward PyTypeObject PgSourceType = { -#ifndef MS_WIN32 - PyObject_HEAD_INIT(&PyType_Type) -#else PyObject_HEAD_INIT(NULL) -#endif 0, /* ob_size */ "pgsourceobject", /* tp_name */ @@ -3141,7 +3137,8 @@ init_pg(void) *v; /* Initialize here because some WIN platforms get confused otherwise */ - PglargeType.ob_type = PgType.ob_type = PgQueryType.ob_type = &PyType_Type; + PglargeType.ob_type = PgType.ob_type = PgQueryType.ob_type = + PgSourceType.ob_type = &PyType_Type; /* Create the module and add the functions */ mod = Py_InitModule4("_pg", pg_methods, pg__doc__, NULL, PYTHON_API_VERSION);