*
*
* 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
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;
*/
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),
* 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)
{
/* Send out shared cache inval if necessary */
if (!IsBootstrapProcessingMode())
RelationInvalidateHeapTuple(pg_class, tuple);
+ BufferSync();
}
else
{
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
* ----------------
*/
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)
{
* 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);
* ---------------------------------
*/
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);
}
/* --------------------------------
* --------------------------------
*/
bool
-reindex_index(Oid indexId, bool force)
+reindex_index(Oid indexId, bool force, bool inplace)
{
Relation iRel,
indexRelation,
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);
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);
{
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
{
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;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* 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);
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)
{
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
*
* 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