From d7892e026396cffb19ebb760fcd12f966054294b Mon Sep 17 00:00:00 2001 From: Hiroshi Inoue Date: Fri, 8 Dec 2000 06:17:58 +0000 Subject: [PATCH] REINDEX under WAL. --- src/backend/catalog/index.c | 199 ++++++++++++++++++++++++++--- src/backend/commands/indexcmds.c | 8 +- src/backend/tcop/utility.c | 4 +- src/backend/utils/cache/relcache.c | 61 ++++++++- src/include/catalog/index.h | 7 +- 5 files changed, 252 insertions(+), 27 deletions(-) diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index d379246a92..aabc3a33d0 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.130 2000/11/16 22:30:17 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.131 2000/12/08 06:17:57 inoue Exp $ * * * INTERFACE ROUTINES @@ -76,7 +76,7 @@ static void DefaultBuild(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, Node *oldPred, IndexStrategy indexStrategy); static Oid IndexGetRelation(Oid indexId); -static bool activate_index(Oid indexId, bool activate); +static bool activate_index(Oid indexId, bool activate, bool inplace); static bool reindexing = false; @@ -1430,7 +1430,11 @@ setRelhasindex(Oid relid, bool hasindex) */ pg_class = heap_openr(RelationRelationName, RowExclusiveLock); +#ifdef OLD_FILE_NAMING if (!IsIgnoringSystemIndexes()) +#else + if (!IsIgnoringSystemIndexes() && (!IsReindexProcessing() || pg_class->rd_rel->relhasindex)) +#endif /* OLD_FILE_NAMING */ { tuple = SearchSysCacheCopy(RELOID, ObjectIdGetDatum(relid), @@ -1462,7 +1466,11 @@ setRelhasindex(Oid relid, bool hasindex) * Update hasindex in pg_class. * ---------------- */ + if (pg_class_scan) + LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE); ((Form_pg_class) GETSTRUCT(tuple))->relhasindex = hasindex; + if (pg_class_scan) + LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_UNLOCK); if (pg_class_scan) { @@ -1471,6 +1479,7 @@ setRelhasindex(Oid relid, bool hasindex) /* Send out shared cache inval if necessary */ if (!IsBootstrapProcessingMode()) RelationInvalidateHeapTuple(pg_class, tuple); + BufferSync(); } else { @@ -1496,6 +1505,75 @@ setRelhasindex(Oid relid, bool hasindex) heap_close(pg_class, RowExclusiveLock); } +#ifndef OLD_FILE_NAMING +void +setNewRelfilenode(Relation relation) +{ + Relation pg_class, idescs[Num_pg_class_indices]; + Oid newrelfilenode; + bool in_place_update = false; + HeapTupleData lockTupleData; + HeapTuple classTuple; + Buffer buffer; + RelationData workrel; + + Assert(!IsSystemRelationName(NameStr(relation->rd_rel->relname)) || relation->rd_rel->relkind == RELKIND_INDEX); + + pg_class = heap_openr(RelationRelationName, RowExclusiveLock); + /* Fetch and lock the classTuple associated with this relation */ + if (!LockClassinfoForUpdate(relation->rd_id, &lockTupleData, &buffer, true)) + elog(ERROR, "setNewRelfilenode impossible to lock class tuple"); + if (IsIgnoringSystemIndexes()) + in_place_update = true; + /* Allocate a new relfilenode */ + newrelfilenode = newoid(); + /* update pg_class tuple with new relfilenode */ + if (!in_place_update) + { + classTuple = heap_copytuple(&lockTupleData); + ReleaseBuffer(buffer); + ((Form_pg_class) GETSTRUCT(classTuple))->relfilenode = newrelfilenode; + heap_update(pg_class, &classTuple->t_self, classTuple, NULL); + } + /* unlink old relfilenode */ + DropRelationBuffers(relation); + smgrunlink(DEFAULT_SMGR, relation); + /* cleanup pg_internal.init if necessary */ + if (relation->rd_isnailed) + unlink(RELCACHE_INIT_FILENAME); + /* create another storage file. Is it a little ugly ? */ + memcpy((char *) &workrel, relation, sizeof(RelationData)); + workrel.rd_node.relNode = newrelfilenode; + heap_storage_create(&workrel); + /* update pg_class tuple with new relfilenode in place */ + if (in_place_update) + { + classTuple = &lockTupleData; + /* Send out shared cache inval if necessary */ + if (!IsBootstrapProcessingMode()) + RelationInvalidateHeapTuple(pg_class, classTuple); + /* Update the buffer in-place */ + LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); + ((Form_pg_class) GETSTRUCT(classTuple))->relfilenode = newrelfilenode; + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + WriteBuffer(buffer); + BufferSync(); + } + /* Keep the catalog indices up to date */ + if (!in_place_update && pg_class->rd_rel->relhasindex) + { + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, + idescs); + CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, classTuple); + CatalogCloseIndices(Num_pg_class_indices, idescs); + heap_freetuple(classTuple); + } + heap_close(pg_class, NoLock); + /* Make sure the relfilenode change */ + CommandCounterIncrement(); +} +#endif /* OLD_FILE_NAMING */ + /* ---------------- * UpdateStats * ---------------- @@ -1552,7 +1630,12 @@ UpdateStats(Oid relid, long reltuples) */ pg_class = heap_openr(RelationRelationName, RowExclusiveLock); +#ifdef OLD_FILE_NAMING in_place_upd = (IsReindexProcessing() || IsBootstrapProcessingMode()); +#else + in_place_upd = (IsIgnoringSystemIndexes() || (IsReindexProcessing() && + relid == RelOid_pg_class)); +#endif /* OLD_FILE_NAMING */ if (!in_place_upd) { @@ -1631,8 +1714,10 @@ UpdateStats(Oid relid, long reltuples) * visibility of changes, so we cheat. Also cheat if REINDEX. */ rd_rel = (Form_pg_class) GETSTRUCT(tuple); + LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE); rd_rel->relpages = relpages; rd_rel->reltuples = reltuples; + LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_UNLOCK); WriteNoReleaseBuffer(pg_class_scan->rs_cbuf); if (!IsBootstrapProcessingMode()) RelationInvalidateHeapTuple(pg_class, tuple); @@ -1924,11 +2009,11 @@ IndexGetRelation(Oid indexId) * --------------------------------- */ static bool -activate_index(Oid indexId, bool activate) +activate_index(Oid indexId, bool activate, bool inplace) { if (!activate) /* Currently does nothing */ return true; - return reindex_index(indexId, false); + return reindex_index(indexId, false, inplace); } /* -------------------------------- @@ -1936,7 +2021,7 @@ activate_index(Oid indexId, bool activate) * -------------------------------- */ bool -reindex_index(Oid indexId, bool force) +reindex_index(Oid indexId, bool force, bool inplace) { Relation iRel, indexRelation, @@ -1996,18 +2081,25 @@ reindex_index(Oid indexId, bool force) if (iRel == NULL) elog(ERROR, "reindex_index: can't open index relation"); +#ifndef OLD_FILE_NAMING + if (!inplace) + setNewRelfilenode(iRel); +#endif /* OLD_FILE_NAMING */ /* Obtain exclusive lock on it, just to be sure */ LockRelation(iRel, AccessExclusiveLock); - /* - * Release any buffers associated with this index. If they're dirty, - * they're just dropped without bothering to flush to disk. - */ - DropRelationBuffers(iRel); - - /* Now truncate the actual data and set blocks to zero */ - smgrtruncate(DEFAULT_SMGR, iRel, 0); - iRel->rd_nblocks = 0; + if (inplace) + { + /* + * Release any buffers associated with this index. If they're dirty, + * they're just dropped without bothering to flush to disk. + */ + DropRelationBuffers(iRel); + + /* Now truncate the actual data and set blocks to zero */ + smgrtruncate(DEFAULT_SMGR, iRel, 0); + iRel->rd_nblocks = 0; + } /* Initialize the index and rebuild */ InitIndexStrategy(indexInfo->ii_NumIndexAttrs, iRel, accessMethodId); @@ -2064,15 +2156,57 @@ reindex_relation(Oid relid, bool force) bool old, reindexed; + bool deactivate_needed, overwrite, upd_pg_class_inplace; +#ifdef OLD_FILE_NAMING + overwrite = upd_pg_class_inplace = deactivate_needed = true; +#else + Relation rel; + overwrite = upd_pg_class_inplace = deactivate_needed = false; + /* + * avoid heap_update() pg_class tuples while processing + * reindex for pg_class. + */ + if (IsIgnoringSystemIndexes()) + upd_pg_class_inplace = true; + /* + * ignore the indexes of the target system relation while processing + * reindex. + */ + rel = RelationIdGetRelation(relid); + if (!IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(rel->rd_rel->relname))) + deactivate_needed = true; +#ifndef ENABLE_REINDEX_NAILED_RELATIONS + /* + * nailed relations are never updated. + * We couldn't keep the consistency between the relation + * descriptors and pg_class tuples. + */ + if (rel->rd_isnailed) + { + if (IsIgnoringSystemIndexes()) + { + overwrite = true; + deactivate_needed = true; + } + else + elog(ERROR, "the target relation %u is nailed", relid); + } +#endif /* ENABLE_REINDEX_NAILED_RELATIONS */ + RelationClose(rel); +#endif /* OLD_FILE_NAMING */ old = SetReindexProcessing(true); - if (IndexesAreActive(relid, true)) + if (deactivate_needed) { - if (!force) + if (IndexesAreActive(relid, upd_pg_class_inplace)) { - SetReindexProcessing(old); - return false; + if (!force) + { + SetReindexProcessing(old); + return false; + } + activate_indexes_of_a_table(relid, false); + CommandCounterIncrement(); } - activate_indexes_of_a_table(relid, false); } indexRelation = heap_openr(IndexRelationName, AccessShareLock); @@ -2085,7 +2219,7 @@ reindex_relation(Oid relid, bool force) { Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple); - if (activate_index(index->indexrelid, true)) + if (activate_index(index->indexrelid, true, overwrite)) reindexed = true; else { @@ -2096,7 +2230,30 @@ reindex_relation(Oid relid, bool force) heap_endscan(scan); heap_close(indexRelation, AccessShareLock); if (reindexed) - setRelhasindex(relid, true); + /* + * Ok,we could use the reindexed indexes of the target + * system relation now. + */ + { + if (deactivate_needed) + { + if (!overwrite && relid == RelOid_pg_class) + { + /* + * For pg_class, relhasindex should be set + * to true here in place. + */ + setRelhasindex(relid, true); + CommandCounterIncrement(); + /* + * However the following setRelhasindex() + * is needed to keep consistency with WAL. + */ + } + setRelhasindex(relid, true); + } + } SetReindexProcessing(old); + return reindexed; } diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 788701b20f..8e362399d8 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.41 2000/11/16 22:30:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.42 2000/12/08 06:17:58 inoue Exp $ * *------------------------------------------------------------------------- */ @@ -653,7 +653,11 @@ ReindexIndex(const char *name, bool force /* currently unused */ ) elog(ERROR, "relation \"%s\" is of type \"%c\"", name, ((Form_pg_class) GETSTRUCT(tuple))->relkind); - if (!reindex_index(tuple->t_data->t_oid, force)) +#ifdef OLD_FILE_NAMING + if (!reindex_index(tuple->t_data->t_oid, force, false)) +#else + if (!reindex_index(tuple->t_data->t_oid, force, false)) +#endif /* OLD_FILE_NAMING */ elog(NOTICE, "index \"%s\" wasn't reindexed", name); ReleaseSysCache(tuple); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index e725ff391f..03df9c1f3d 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.103 2000/11/16 22:30:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.104 2000/12/08 06:17:58 inoue Exp $ * *------------------------------------------------------------------------- */ @@ -866,6 +866,7 @@ ProcessUtility(Node *parsetree, relname = (char *) stmt->name; if (IsSystemRelationName(relname)) { +#ifdef OLD_FILE_NAMING if (!allowSystemTableMods && IsSystemRelationName(relname)) elog(ERROR, "\"%s\" is a system table. call REINDEX under standalone postgres with -O -P options", relname); @@ -873,6 +874,7 @@ ProcessUtility(Node *parsetree, elog(ERROR, "\"%s\" is a system table. call REINDEX under standalone postgres with -P -O options", relname); +#endif /* OLD_FILE_NAMING */ } if (!pg_ownercheck(GetUserId(), relname, RELNAME)) elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index e4551d4c60..deb8cc67df 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.118 2000/11/30 18:38:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.119 2000/12/08 06:17:56 inoue Exp $ * *------------------------------------------------------------------------- */ @@ -250,6 +250,10 @@ do { \ /* non-export function prototypes */ static void RelationClearRelation(Relation relation, bool rebuildIt); +#ifdef ENABLE_REINDEX_NAILED_RELATIONS +static void RelationReloadClassinfo(Relation relation); +#endif /* ENABLE_REINDEX_NAILED_RELATIONS */ +static void RelationResetRelation(Relation relation, bool rebuildIt); static void RelationFlushRelation(Relation *relationPtr, int skipLocalRelations); static Relation RelationNameCacheGetRelation(const char *relationName); @@ -387,6 +391,15 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo) HeapTuple return_tuple; pg_class_desc = heap_openr(RelationRelationName, AccessShareLock); + /* + * If the indexes of pg_class are deactivated + * we have to call scan_pg_rel_seq() instead. + */ + if (!pg_class_desc->rd_rel->relhasindex) + { + heap_close(pg_class_desc, AccessShareLock); + return scan_pg_rel_seq(buildinfo); + } switch (buildinfo.infotype) { @@ -1555,6 +1568,45 @@ RelationClose(Relation relation) RelationDecrementReferenceCount(relation); } +#ifdef ENABLE_REINDEX_NAILED_RELATIONS +/* -------------------------------- + * RelationReloadClassinfo + * + * This function is especially for nailed relations. + * relhasindex/relfilenode could be changed even for + * nailed relations. + * -------------------------------- + */ +static void +RelationReloadClassinfo(Relation relation) +{ + RelationBuildDescInfo buildinfo; + HeapTuple pg_class_tuple; + Form_pg_class relp; + + if (!relation->rd_rel) + return; + buildinfo.infotype = INFO_RELID; + buildinfo.i.info_id = relation->rd_id; + pg_class_tuple = ScanPgRelation(buildinfo); + if (!HeapTupleIsValid(pg_class_tuple)) + { + elog(ERROR, "RelationReloadClassinfo system relation id=%d doesn't exist", relation->rd_id); + return; + } + RelationCacheDelete(relation); + relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); + memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE); + relation->rd_node.relNode = relp->relfilenode; + RelationCacheInsert(relation); + heap_freetuple(pg_class_tuple); +fprintf(stderr, "RelationClearRelation nailed %s hasindex=%d relfilenode=%d,%d\n", +RelationGetRelationName(relation), relation->rd_rel->relhasindex, +relation->rd_rel->relfilenode, relation->rd_node.relNode); + + return; +} +#endif /* ENABLE_REINDEX_NAILED_RELATIONS */ /* -------------------------------- * RelationClearRelation * @@ -1588,7 +1640,14 @@ RelationClearRelation(Relation relation, bool rebuildIt) * we'd be unable to recover. */ if (relation->rd_isnailed) +#ifdef ENABLE_REINDEX_NAILED_RELATIONS + { + RelationReloadClassinfo(relation); +#endif /* ENABLE_REINDEX_NAILED_RELATIONS */ return; +#ifdef ENABLE_REINDEX_NAILED_RELATIONS + } +#endif /* ENABLE_REINDEX_NAILED_RELATIONS */ /* * Remove relation from hash tables diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 967bffb4aa..4a7672350a 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: index.h,v 1.30 2000/11/08 22:10:01 tgl Exp $ + * $Id: index.h,v 1.31 2000/12/08 06:17:56 inoue Exp $ * *------------------------------------------------------------------------- */ @@ -49,13 +49,16 @@ extern void FormIndexDatum(IndexInfo *indexInfo, extern void UpdateStats(Oid relid, long reltuples); extern bool IndexesAreActive(Oid relid, bool comfirmCommitted); extern void setRelhasindex(Oid relid, bool hasindex); +#ifndef OLD_FILE_NAMING +extern void setNewRelfilenode(Relation relation); +#endif /* OLD_FILE_NAMING */ extern bool SetReindexProcessing(bool processing); extern bool IsReindexProcessing(void); extern void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, Node *oldPred); -extern bool reindex_index(Oid indexId, bool force); +extern bool reindex_index(Oid indexId, bool force, bool inplace); extern bool activate_indexes_of_a_table(Oid relid, bool activate); extern bool reindex_relation(Oid relid, bool force); -- 2.40.0