88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.90 2000/10/21 15:43:14 vadim Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.91 2000/10/24 09:56:07 vadim Exp $
1212 *
1313 *
1414 * INTERFACE ROUTINES
@@ -93,9 +93,13 @@ void heap_redo(XLogRecPtr lsn, XLogRecord *record);
9393void heap_undo (XLogRecPtr lsn ,XLogRecord * record );
9494void heap_desc (char * buf ,uint8 xl_info ,char * rec );
9595
96+ XLogRecPtr log_heap_move (Relation reln ,ItemPointerData from ,HeapTuple newtup );
97+
9698/* comments are in heap_update */
9799static xl_heaptid _locked_tuple_ ;
98100static void _heap_unlock_tuple (void * data );
101+ static XLogRecPtr log_heap_update (Relation reln ,ItemPointerData from ,
102+ HeapTuple newtup ,bool move );
99103
100104static void HeapPageCleanup (Buffer buffer );
101105
@@ -1706,22 +1710,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
17061710#ifdef XLOG
17071711/* XLOG stuff */
17081712{
1709- xl_heap_update xlrec ;
1710- XLogRecPtr recptr ;
1711-
1712- xlrec .target .node = relation -> rd_node ;
1713- xlrec .target .cid = GetCurrentCommandId ();
1714- xlrec .target .tid = oldtup .t_self ;
1715- xlrec .newtid = newtup -> t_self ;
1716- xlrec .t_natts = newtup -> t_data -> t_natts ;
1717- xlrec .t_oid = newtup -> t_data -> t_oid ;
1718- xlrec .t_hoff = newtup -> t_data -> t_hoff ;
1719- xlrec .mask = newtup -> t_data -> t_infomask ;
1720-
1721- recptr = XLogInsert (RM_HEAP_ID ,XLOG_HEAP_UPDATE ,
1722- (char * )& xlrec ,SizeOfHeapUpdate ,
1723- (char * )newtup -> t_data + offsetof(HeapTupleHeaderData ,t_bits ),
1724- newtup -> t_len - offsetof(HeapTupleHeaderData ,t_bits ));
1713+ XLogRecPtr recptr = log_heap_update (relation ,
1714+ oldtup .t_self ,newtup , false);
17251715
17261716if (newbuf != buffer )
17271717{
@@ -2019,6 +2009,54 @@ heap_restrpos(HeapScanDesc scan)
20192009
20202010#ifdef XLOG
20212011
2012+ static XLogRecPtr
2013+ log_heap_update (Relation reln ,ItemPointerData from ,
2014+ HeapTuple newtup ,bool move )
2015+ {
2016+ char tbuf [sizeof (xl_heap_update )+ 2 * sizeof (TransactionId )];
2017+ xl_heap_update * xlrec = (xl_heap_update * )tbuf ;
2018+ int hsize = SizeOfHeapUpdate ;
2019+ XLogRecPtr recptr ;
2020+
2021+ xlrec -> target .node = reln -> rd_node ;
2022+ xlrec -> target .tid = from ;
2023+ xlrec -> newtid = newtup -> t_self ;
2024+ xlrec -> t_natts = newtup -> t_data -> t_natts ;
2025+ xlrec -> t_oid = newtup -> t_data -> t_oid ;
2026+ xlrec -> t_hoff = newtup -> t_data -> t_hoff ;
2027+ xlrec -> mask = newtup -> t_data -> t_infomask ;
2028+
2029+ if (move )/* remember xmin & xmax */
2030+ {
2031+ TransactionId xmax ;
2032+
2033+ xlrec -> target .cid = (CommandId )newtup -> t_data -> t_xmin ;
2034+ if (newtup -> t_data -> t_infomask & HEAP_XMAX_INVALID ||
2035+ newtup -> t_data -> t_infomask & HEAP_MARKED_FOR_UPDATE )
2036+ xmax = InvalidTransactionId ;
2037+ else
2038+ xmax = newtup -> t_data -> t_xmax ;
2039+ memcpy (tbuf + hsize ,& xmax ,sizeof (TransactionId ));
2040+ hsize += sizeof (TransactionId );
2041+ }
2042+ else
2043+ xlrec -> target .cid = GetCurrentCommandId ();
2044+
2045+ recptr = XLogInsert (RM_HEAP_ID ,
2046+ (move ) ?XLOG_HEAP_MOVE :XLOG_HEAP_UPDATE ,
2047+ tbuf ,hsize ,
2048+ (char * )newtup -> t_data + offsetof(HeapTupleHeaderData ,t_bits ),
2049+ newtup -> t_len - offsetof(HeapTupleHeaderData ,t_bits ));
2050+
2051+ return (recptr );
2052+ }
2053+
2054+ XLogRecPtr
2055+ log_heap_move (Relation reln ,ItemPointerData from ,HeapTuple newtup )
2056+ {
2057+ return (log_heap_update (reln ,from ,newtup , true));
2058+ }
2059+
20222060static void
20232061heap_xlog_delete (bool redo ,XLogRecPtr lsn ,XLogRecord * record )
20242062{
@@ -2159,6 +2197,7 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
21592197htup -> t_hoff = xlrec -> t_hoff ;
21602198htup -> t_xmin = record -> xl_xid ;
21612199htup -> t_cmin = xlrec -> target .cid ;
2200+ htup -> t_xmax = htup -> t_cmax = 0 ;
21622201htup -> t_infomask = HEAP_XMAX_INVALID |HEAP_XMIN_COMMITTED |xlrec -> mask ;
21632202
21642203offnum = PageAddItem (page , (Item )htup ,newlen ,
@@ -2210,8 +2249,11 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
22102249
22112250}
22122251
2252+ /*
2253+ * Handles UPDATE & MOVE
2254+ */
22132255static void
2214- heap_xlog_update (bool redo ,XLogRecPtr lsn ,XLogRecord * record )
2256+ heap_xlog_update (bool redo ,XLogRecPtr lsn ,XLogRecord * record , bool move )
22152257{
22162258xl_heap_update * xlrec = (xl_heap_update * )XLogRecGetData (record );
22172259Relation reln = XLogOpenRelation (redo ,RM_HEAP_ID ,xlrec -> target .node );
@@ -2282,26 +2324,46 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record)
22822324
22832325if (redo )
22842326{
2285- htup -> t_xmax = record -> xl_xid ;
2286- htup -> t_cmax = xlrec -> target .cid ;
2287- htup -> t_infomask &= ~(HEAP_XMAX_INVALID |HEAP_MARKED_FOR_UPDATE );
2288- htup -> t_infomask |=HEAP_XMAX_COMMITTED ;
2327+ if (move )
2328+ {
2329+ TransactionIdStore (record -> xl_xid , (TransactionId * )& (htup -> t_cmin ));
2330+ htup -> t_infomask &=
2331+ ~(HEAP_XMIN_COMMITTED |HEAP_XMIN_INVALID |HEAP_MOVED_IN );
2332+ htup -> t_infomask |=HEAP_MOVED_OFF ;
2333+ }
2334+ else
2335+ {
2336+ htup -> t_xmax = record -> xl_xid ;
2337+ htup -> t_cmax = xlrec -> target .cid ;
2338+ htup -> t_infomask &= ~(HEAP_XMAX_COMMITTED |
2339+ HEAP_XMAX_INVALID |HEAP_MARKED_FOR_UPDATE );
2340+ }
22892341PageSetLSN (page ,lsn );
22902342PageSetSUI (page ,ThisStartUpID );
22912343UnlockAndWriteBuffer (buffer );
22922344gotonewt ;
22932345}
22942346
22952347/* undo... is it our tuple ? */
2296- if (htup -> t_xmax != record -> xl_xid || htup -> t_cmax != xlrec -> target .cid )
2348+ if ((!move && (htup -> t_xmax != record -> xl_xid ||
2349+ htup -> t_cmax != xlrec -> target .cid ))||
2350+ xlrec -> target .cid != (CommandId )htup -> t_xmin ||
2351+ htup -> t_cmin != (CommandId )record -> xl_xid )
22972352{
22982353if (!InRecovery )
22992354elog (STOP ,"heap_update_undo: invalid old tuple in rollback" );
23002355UnlockAndReleaseBuffer (buffer );
23012356}
23022357else /* undo */
23032358{
2304- htup -> t_infomask |=HEAP_XMAX_INVALID ;
2359+ if (move )
2360+ {
2361+ htup -> t_infomask &= ~(HEAP_XMIN_INVALID |
2362+ HEAP_MOVED_IN |HEAP_MOVED_OFF );
2363+ htup -> t_infomask |=HEAP_XMIN_COMMITTED ;
2364+ }
2365+ else
2366+ htup -> t_infomask |=HEAP_XMAX_INVALID ;
23052367UnlockAndWriteBuffer (buffer );
23062368}
23072369
@@ -2329,25 +2391,45 @@ newt:;
23292391
23302392if (redo )
23312393{
2332- char tbuf [MaxTupleSize ];
2333- uint32 newlen = record -> xl_len - SizeOfHeapUpdate ;
2394+ char tbuf [MaxTupleSize ];
2395+ int hsize ;
2396+ uint32 newlen ;
23342397
23352398if (XLByteLE (lsn ,PageGetLSN (page )))/* changes are applied */
23362399{
23372400UnlockAndReleaseBuffer (buffer );
23382401return ;
23392402}
23402403
2404+ hsize = SizeOfHeapUpdate ;
2405+ if (move )
2406+ hsize += sizeof (TransactionId );
2407+ newlen = record -> xl_len - hsize ;
2408+
23412409htup = (HeapTupleHeader )tbuf ;
23422410memcpy (tbuf + offsetof(HeapTupleHeaderData ,t_bits ),
2343- (char * )xlrec + SizeOfHeapUpdate ,newlen );
2411+ (char * )xlrec + hsize ,newlen );
23442412newlen += offsetof(HeapTupleHeaderData ,t_bits );
23452413htup -> t_oid = xlrec -> t_oid ;
23462414htup -> t_natts = xlrec -> t_natts ;
23472415htup -> t_hoff = xlrec -> t_hoff ;
2348- htup -> t_xmin = record -> xl_xid ;
2349- htup -> t_cmin = xlrec -> target .cid ;
2350- htup -> t_infomask = HEAP_XMAX_INVALID |HEAP_XMIN_COMMITTED |xlrec -> mask ;
2416+ if (move )
2417+ {
2418+ htup -> t_xmin = (TransactionId )xlrec -> target .cid ;
2419+ memcpy (& (htup -> t_xmax ),
2420+ (char * )xlrec + SizeOfHeapUpdate ,sizeof (TransactionId ));
2421+ htup -> t_infomask = xlrec -> mask ;
2422+ htup -> t_infomask &= ~(HEAP_XMIN_COMMITTED |
2423+ HEAP_XMIN_INVALID |HEAP_MOVED_OFF );
2424+ htup -> t_infomask |=HEAP_MOVED_IN ;
2425+ }
2426+ else
2427+ {
2428+ htup -> t_xmin = record -> xl_xid ;
2429+ htup -> t_cmin = xlrec -> target .cid ;
2430+ htup -> t_xmax = htup -> t_cmax = 0 ;
2431+ htup -> t_infomask = HEAP_XMAX_INVALID |xlrec -> mask ;
2432+ }
23512433
23522434offnum = PageAddItem (page , (Item )htup ,newlen ,
23532435ItemPointerGetOffsetNumber (& (xlrec -> newtid )),
@@ -2385,7 +2467,10 @@ newt:;
23852467
23862468/* is it our tuple ? */
23872469Assert (PageGetSUI (page )== ThisStartUpID );
2388- if (htup -> t_xmin != record -> xl_xid || htup -> t_cmin != xlrec -> target .cid )
2470+ if ((!move && (htup -> t_xmin != record -> xl_xid ||
2471+ htup -> t_cmin != xlrec -> target .cid ))||
2472+ xlrec -> target .cid != (CommandId )htup -> t_xmin ||
2473+ htup -> t_cmin != (CommandId )record -> xl_xid )
23892474{
23902475if (!InRecovery )
23912476elog (STOP ,"heap_update_undo: invalid new tuple in rollback" );
@@ -2448,11 +2533,9 @@ void heap_redo(XLogRecPtr lsn, XLogRecord *record)
24482533else if (info == XLOG_HEAP_DELETE )
24492534heap_xlog_delete (true,lsn ,record );
24502535else if (info == XLOG_HEAP_UPDATE )
2451- heap_xlog_update (true,lsn ,record );
2452- #ifdef NOT_USED
2536+ heap_xlog_update (true,lsn ,record , false);
24532537else if (info == XLOG_HEAP_MOVE )
2454- heap_xlog_move (true ,lsn ,record );
2455- #endif
2538+ heap_xlog_update (true,lsn ,record , true);
24562539else
24572540elog (STOP ,"heap_redo: unknown op code %u" ,info );
24582541}
@@ -2466,11 +2549,9 @@ void heap_undo(XLogRecPtr lsn, XLogRecord *record)
24662549else if (info == XLOG_HEAP_DELETE )
24672550heap_xlog_delete (false,lsn ,record );
24682551else if (info == XLOG_HEAP_UPDATE )
2469- heap_xlog_update (false,lsn ,record );
2470- #ifdef NOT_USED
2552+ heap_xlog_update (false,lsn ,record , false);
24712553else if (info == XLOG_HEAP_MOVE )
2472- heap_xlog_move (false ,lsn ,record );
2473- #endif
2554+ heap_xlog_update (false,lsn ,record , true);
24742555else
24752556elog (STOP ,"heap_undo: unknown op code %u" ,info );
24762557}
@@ -2509,19 +2590,13 @@ heap_desc(char *buf, uint8 xl_info, char* rec)
25092590strcat (buf ,"delete: " );
25102591out_target (buf ,& (xlrec -> target ));
25112592}
2512- else if (info == XLOG_HEAP_UPDATE )
2593+ else if (info == XLOG_HEAP_UPDATE || info == XLOG_HEAP_MOVE )
25132594{
25142595xl_heap_update * xlrec = (xl_heap_update * )rec ;
2515- strcat (buf ,"update: " );
2516- out_target (buf ,& (xlrec -> target ));
2517- sprintf (buf + strlen (buf ),"; new %u/%u" ,
2518- ItemPointerGetBlockNumber (& (xlrec -> newtid )),
2519- ItemPointerGetOffsetNumber (& (xlrec -> newtid )));
2520- }
2521- else if (info == XLOG_HEAP_MOVE )
2522- {
2523- xl_heap_move * xlrec = (xl_heap_move * )rec ;
2524- strcat (buf ,"move: " );
2596+ if (info == XLOG_HEAP_UPDATE )
2597+ strcat (buf ,"update: " );
2598+ else
2599+ strcat (buf ,"move: " );
25252600out_target (buf ,& (xlrec -> target ));
25262601sprintf (buf + strlen (buf ),"; new %u/%u" ,
25272602ItemPointerGetBlockNumber (& (xlrec -> newtid )),