88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.41 2000/11 /14 18:37:45 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.42 2001/01 /14 22:21:05 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
1515#include "postgres.h"
1616
17- #include <errno.h>
1817#include <fcntl.h>
1918#include <stdlib.h>
2019#include <string.h>
2827#include "utils/syscache.h"
2928
3029
30+ static bool PhonyHeapTupleSatisfiesNow (HeapTupleHeader tuple );
31+
32+
3133/*
3234 * ExpandDatabasePath resolves a proposed database path (obtained from
3335 * pg_database.datpath) to a full absolute path for further consumption.
@@ -136,11 +138,9 @@ GetRawDatabaseInfo(const char *name, Oid *db_id, char *path)
136138{
137139 int dbfd ;
138140 int nbytes ;
139- int max ,
140- i ;
141+ int pathlen ;
141142 HeapTupleData tup ;
142143 Page pg ;
143- PageHeader ph ;
144144 char * dbfname ;
145145 Form_pg_database tup_db ;
146146
@@ -157,7 +157,7 @@ GetRawDatabaseInfo(const char *name, Oid *db_id, char *path)
157157#endif
158158
159159 if ((dbfd = open (dbfname , O_RDONLY | PG_BINARY , 0 )) < 0 )
160- elog (FATAL , "cannot open %s: %s " , dbfname , strerror ( errno ) );
160+ elog (FATAL , "cannot open %s: %m " , dbfname );
161161
162162 pfree (dbfname );
163163
@@ -179,38 +179,38 @@ GetRawDatabaseInfo(const char *name, Oid *db_id, char *path)
179179 * ----------------
180180 */
181181 pg = (Page ) palloc (BLCKSZ );
182- ph = (PageHeader ) pg ;
183182
184183 while ((nbytes = read (dbfd , pg , BLCKSZ )) == BLCKSZ )
185184 {
186- max = PageGetMaxOffsetNumber (pg );
185+ OffsetNumber max = PageGetMaxOffsetNumber (pg );
186+ OffsetNumber lineoff ;
187187
188188 /* look at each tuple on the page */
189- for (i = 0 ; i < max ; i ++ )
189+ for (lineoff = FirstOffsetNumber ; lineoff <= max ; lineoff ++ )
190190 {
191- int offset ;
191+ ItemId lpp = PageGetItemId ( pg , lineoff ) ;
192192
193193 /* if it's a freed tuple, ignore it */
194- if (!( ph -> pd_linp [ i ]. lp_flags & LP_USED ))
194+ if (!ItemIdIsUsed ( lpp ))
195195 continue ;
196196
197197 /* get a pointer to the tuple itself */
198- offset = (int ) ph -> pd_linp [i ].lp_off ;
199198 tup .t_datamcxt = NULL ;
200- tup .t_data = (HeapTupleHeader ) ((( char * ) pg ) + offset );
199+ tup .t_data = (HeapTupleHeader ) PageGetItem ( pg , lpp );
201200
202- /*
203- * if the tuple has been deleted (the database was destroyed),
204- * skip this tuple. XXX warning, will robinson: violation of
205- * transaction semantics happens right here. we should check
206- * to be sure that the xact that deleted this tuple actually
207- * committed. Only way to do that at init time is to paw over
208- * the log relation by hand, too. Instead we take the
209- * conservative assumption that if someone tried to delete it,
210- * it's gone. The other side of the coin is that we might
211- * accept a tuple that was stored and never committed. All in
212- * all, this code is pretty shaky. We will cross-check our
213- * result in ReverifyMyDatabase() in postinit.c.
201+ /*--------------------
202+ * Check to see if tuple is valid (committed).
203+ *
204+ * XXX warning, will robinson: violation of transaction semantics
205+ * happens right here. We cannot really determine if the tuple
206+ * is valid without checking transaction commit status, and the
207+ * only way to do that at init time is to paw over pg_log by hand,
208+ * too. Instead of checking, we assume that the inserting
209+ * transaction committed, and that any deleting transaction did
210+ * also, unless shown otherwise by on-row commit status bits.
211+ *
212+ * All in all, this code is pretty shaky. We will cross-check
213+ * our result in ReverifyMyDatabase() in postinit.c.
214214 *
215215 * NOTE: if a bogus tuple in pg_database prevents connection to a
216216 * valid database, a fix is to connect to another database and
@@ -220,12 +220,10 @@ GetRawDatabaseInfo(const char *name, Oid *db_id, char *path)
220220 * XXX wouldn't it be better to let new backends read the
221221 * database OID from a flat file, handled the same way we
222222 * handle the password relation?
223+ *--------------------
223224 */
224- if (tup .t_data -> t_infomask & HEAP_XMIN_INVALID )
225- continue ; /* inserting xact known aborted */
226- if (TransactionIdIsValid ((TransactionId ) tup .t_data -> t_xmax ) &&
227- !(tup .t_data -> t_infomask & HEAP_XMAX_INVALID ))
228- continue ; /* deleting xact happened, not known aborted */
225+ if (! PhonyHeapTupleSatisfiesNow (tup .t_data ))
226+ continue ;
229227
230228 /*
231229 * Okay, see if this is the one we want.
@@ -236,9 +234,11 @@ GetRawDatabaseInfo(const char *name, Oid *db_id, char *path)
236234 {
237235 /* Found it; extract the OID and the database path. */
238236 * db_id = tup .t_data -> t_oid ;
239- strncpy (path , VARDATA (& (tup_db -> datpath )),
240- (VARSIZE (& (tup_db -> datpath )) - VARHDRSZ ));
241- * (path + VARSIZE (& (tup_db -> datpath )) - VARHDRSZ ) = '\0' ;
237+ pathlen = VARSIZE (& (tup_db -> datpath )) - VARHDRSZ ;
238+ if (pathlen >= MAXPGPATH )
239+ pathlen = MAXPGPATH - 1 ; /* pure paranoia */
240+ strncpy (path , VARDATA (& (tup_db -> datpath )), pathlen );
241+ path [pathlen ] = '\0' ;
242242 goto done ;
243243 }
244244 }
@@ -251,4 +251,37 @@ GetRawDatabaseInfo(const char *name, Oid *db_id, char *path)
251251done :
252252 close (dbfd );
253253 pfree (pg );
254- } /* GetRawDatabaseInfo() */
254+ }
255+
256+ /*
257+ * PhonyHeapTupleSatisfiesNow --- cut-down tuple time qual test
258+ *
259+ * This is a simplified version of HeapTupleSatisfiesNow() that does not
260+ * depend on having transaction commit info available. Any transaction
261+ * that touched the tuple is assumed committed unless later marked invalid.
262+ * (While we could think about more complex rules, this seems appropriate
263+ * for examining pg_database, since both CREATE DATABASE and DROP DATABASE
264+ * are non-roll-back-able.)
265+ */
266+ static bool
267+ PhonyHeapTupleSatisfiesNow (HeapTupleHeader tuple )
268+ {
269+ if (!(tuple -> t_infomask & HEAP_XMIN_COMMITTED ))
270+ {
271+ if (tuple -> t_infomask & HEAP_XMIN_INVALID )
272+ return false;
273+
274+ if (tuple -> t_infomask & HEAP_MOVED_OFF )
275+ return false;
276+ /* else assume committed */
277+ }
278+
279+ if (tuple -> t_infomask & HEAP_XMAX_INVALID ) /* xid invalid or aborted */
280+ return true;
281+
282+ /* assume xmax transaction committed */
283+ if (tuple -> t_infomask & HEAP_MARKED_FOR_UPDATE )
284+ return true;
285+
286+ return false;
287+ }
0 commit comments