8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*
14
14
* INTERFACE ROUTINES
@@ -93,9 +93,13 @@ void heap_redo(XLogRecPtr lsn, XLogRecord *record);
93
93
void heap_undo (XLogRecPtr lsn , XLogRecord * record );
94
94
void heap_desc (char * buf , uint8 xl_info , char * rec );
95
95
96
+ XLogRecPtr log_heap_move (Relation reln , ItemPointerData from , HeapTuple newtup );
97
+
96
98
/* comments are in heap_update */
97
99
static xl_heaptid _locked_tuple_ ;
98
100
static void _heap_unlock_tuple (void * data );
101
+ static XLogRecPtr log_heap_update (Relation reln , ItemPointerData from ,
102
+ HeapTuple newtup , bool move );
99
103
100
104
static void HeapPageCleanup (Buffer buffer );
101
105
@@ -1706,22 +1710,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
1706
1710
#ifdef XLOG
1707
1711
/* XLOG stuff */
1708
1712
{
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);
1725
1715
1726
1716
if (newbuf != buffer )
1727
1717
{
@@ -2019,6 +2009,54 @@ heap_restrpos(HeapScanDesc scan)
2019
2009
2020
2010
#ifdef XLOG
2021
2011
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
+
2022
2060
static void
2023
2061
heap_xlog_delete (bool redo , XLogRecPtr lsn , XLogRecord * record )
2024
2062
{
@@ -2159,6 +2197,7 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
2159
2197
htup -> t_hoff = xlrec -> t_hoff ;
2160
2198
htup -> t_xmin = record -> xl_xid ;
2161
2199
htup -> t_cmin = xlrec -> target .cid ;
2200
+ htup -> t_xmax = htup -> t_cmax = 0 ;
2162
2201
htup -> t_infomask = HEAP_XMAX_INVALID | HEAP_XMIN_COMMITTED | xlrec -> mask ;
2163
2202
2164
2203
offnum = PageAddItem (page , (Item )htup , newlen ,
@@ -2210,8 +2249,11 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
2210
2249
2211
2250
}
2212
2251
2252
+ /*
2253
+ * Handles UPDATE & MOVE
2254
+ */
2213
2255
static void
2214
- heap_xlog_update (bool redo , XLogRecPtr lsn , XLogRecord * record )
2256
+ heap_xlog_update (bool redo , XLogRecPtr lsn , XLogRecord * record , bool move )
2215
2257
{
2216
2258
xl_heap_update * xlrec = (xl_heap_update * ) XLogRecGetData (record );
2217
2259
Relation reln = XLogOpenRelation (redo , RM_HEAP_ID , xlrec -> target .node );
@@ -2282,26 +2324,46 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record)
2282
2324
2283
2325
if (redo )
2284
2326
{
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
+ }
2289
2341
PageSetLSN (page , lsn );
2290
2342
PageSetSUI (page , ThisStartUpID );
2291
2343
UnlockAndWriteBuffer (buffer );
2292
2344
goto newt ;
2293
2345
}
2294
2346
2295
2347
/* 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 )
2297
2352
{
2298
2353
if (!InRecovery )
2299
2354
elog (STOP , "heap_update_undo: invalid old tuple in rollback" );
2300
2355
UnlockAndReleaseBuffer (buffer );
2301
2356
}
2302
2357
else /* undo */
2303
2358
{
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 ;
2305
2367
UnlockAndWriteBuffer (buffer );
2306
2368
}
2307
2369
@@ -2329,25 +2391,45 @@ newt:;
2329
2391
2330
2392
if (redo )
2331
2393
{
2332
- char tbuf [MaxTupleSize ];
2333
- uint32 newlen = record -> xl_len - SizeOfHeapUpdate ;
2394
+ char tbuf [MaxTupleSize ];
2395
+ int hsize ;
2396
+ uint32 newlen ;
2334
2397
2335
2398
if (XLByteLE (lsn , PageGetLSN (page ))) /* changes are applied */
2336
2399
{
2337
2400
UnlockAndReleaseBuffer (buffer );
2338
2401
return ;
2339
2402
}
2340
2403
2404
+ hsize = SizeOfHeapUpdate ;
2405
+ if (move )
2406
+ hsize += sizeof (TransactionId );
2407
+ newlen = record -> xl_len - hsize ;
2408
+
2341
2409
htup = (HeapTupleHeader ) tbuf ;
2342
2410
memcpy (tbuf + offsetof(HeapTupleHeaderData , t_bits ),
2343
- (char * )xlrec + SizeOfHeapUpdate , newlen );
2411
+ (char * )xlrec + hsize , newlen );
2344
2412
newlen += offsetof(HeapTupleHeaderData , t_bits );
2345
2413
htup -> t_oid = xlrec -> t_oid ;
2346
2414
htup -> t_natts = xlrec -> t_natts ;
2347
2415
htup -> 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
+ }
2351
2433
2352
2434
offnum = PageAddItem (page , (Item )htup , newlen ,
2353
2435
ItemPointerGetOffsetNumber (& (xlrec -> newtid )),
@@ -2385,7 +2467,10 @@ newt:;
2385
2467
2386
2468
/* is it our tuple ? */
2387
2469
Assert (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 )
2389
2474
{
2390
2475
if (!InRecovery )
2391
2476
elog (STOP , "heap_update_undo: invalid new tuple in rollback" );
@@ -2448,11 +2533,9 @@ void heap_redo(XLogRecPtr lsn, XLogRecord *record)
2448
2533
else if (info == XLOG_HEAP_DELETE )
2449
2534
heap_xlog_delete (true, lsn , record );
2450
2535
else if (info == XLOG_HEAP_UPDATE )
2451
- heap_xlog_update (true, lsn , record );
2452
- #ifdef NOT_USED
2536
+ heap_xlog_update (true, lsn , record , false);
2453
2537
else if (info == XLOG_HEAP_MOVE )
2454
- heap_xlog_move (true , lsn , record );
2455
- #endif
2538
+ heap_xlog_update (true, lsn , record , true);
2456
2539
else
2457
2540
elog (STOP , "heap_redo: unknown op code %u" , info );
2458
2541
}
@@ -2466,11 +2549,9 @@ void heap_undo(XLogRecPtr lsn, XLogRecord *record)
2466
2549
else if (info == XLOG_HEAP_DELETE )
2467
2550
heap_xlog_delete (false, lsn , record );
2468
2551
else if (info == XLOG_HEAP_UPDATE )
2469
- heap_xlog_update (false, lsn , record );
2470
- #ifdef NOT_USED
2552
+ heap_xlog_update (false, lsn , record , false);
2471
2553
else if (info == XLOG_HEAP_MOVE )
2472
- heap_xlog_move (false , lsn , record );
2473
- #endif
2554
+ heap_xlog_update (false, lsn , record , true);
2474
2555
else
2475
2556
elog (STOP , "heap_undo: unknown op code %u" , info );
2476
2557
}
@@ -2509,19 +2590,13 @@ heap_desc(char *buf, uint8 xl_info, char* rec)
2509
2590
strcat (buf , "delete: " );
2510
2591
out_target (buf , & (xlrec -> target ));
2511
2592
}
2512
- else if (info == XLOG_HEAP_UPDATE )
2593
+ else if (info == XLOG_HEAP_UPDATE || info == XLOG_HEAP_MOVE )
2513
2594
{
2514
2595
xl_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: " );
2525
2600
out_target (buf , & (xlrec -> target ));
2526
2601
sprintf (buf + strlen (buf ), "; new %u/%u" ,
2527
2602
ItemPointerGetBlockNumber (& (xlrec -> newtid )),
0 commit comments