LCOV - code coverage report
Current view: top level - libs/postgres_ffi/src - nonrelfile_utils.rs (source / functions) Coverage Total Hit
Test: 32f4a56327bc9da697706839ed4836b2a00a408f.info Lines: 88.6 % 88 78
Test Date: 2024-02-07 07:37:29 Functions: 72.7 % 33 24

            Line data    Source code
       1              : //!
       2              : //! Common utilities for dealing with PostgreSQL non-relation files.
       3              : //!
       4              : use crate::pg_constants;
       5              : use crate::transaction_id_precedes;
       6              : use bytes::BytesMut;
       7              : use log::*;
       8              : 
       9              : use super::bindings::MultiXactId;
      10              : 
      11     18935135 : pub fn transaction_id_set_status(xid: u32, status: u8, page: &mut BytesMut) {
      12     18935135 :     trace!(
      13            0 :         "handle_apply_request for RM_XACT_ID-{} (1-commit, 2-abort, 3-sub_commit)",
      14              :         status
      15              :     );
      16              : 
      17     18935135 :     let byteno: usize =
      18     18935135 :         ((xid % pg_constants::CLOG_XACTS_PER_PAGE) / pg_constants::CLOG_XACTS_PER_BYTE) as usize;
      19     18935135 : 
      20     18935135 :     let bshift: u8 =
      21     18935135 :         ((xid % pg_constants::CLOG_XACTS_PER_BYTE) * pg_constants::CLOG_BITS_PER_XACT as u32) as u8;
      22     18935135 : 
      23     18935135 :     page[byteno] =
      24     18935135 :         (page[byteno] & !(pg_constants::CLOG_XACT_BITMASK << bshift)) | (status << bshift);
      25     18935135 : }
      26              : 
      27            0 : pub fn transaction_id_get_status(xid: u32, page: &[u8]) -> u8 {
      28            0 :     let byteno: usize =
      29            0 :         ((xid % pg_constants::CLOG_XACTS_PER_PAGE) / pg_constants::CLOG_XACTS_PER_BYTE) as usize;
      30            0 : 
      31            0 :     let bshift: u8 =
      32            0 :         ((xid % pg_constants::CLOG_XACTS_PER_BYTE) * pg_constants::CLOG_BITS_PER_XACT as u32) as u8;
      33            0 : 
      34            0 :     (page[byteno] >> bshift) & pg_constants::CLOG_XACT_BITMASK
      35            0 : }
      36              : 
      37              : // See CLOGPagePrecedes in clog.c
      38           26 : pub const fn clogpage_precedes(page1: u32, page2: u32) -> bool {
      39           26 :     let mut xid1 = page1 * pg_constants::CLOG_XACTS_PER_PAGE;
      40           26 :     xid1 += pg_constants::FIRST_NORMAL_TRANSACTION_ID + 1;
      41           26 :     let mut xid2 = page2 * pg_constants::CLOG_XACTS_PER_PAGE;
      42           26 :     xid2 += pg_constants::FIRST_NORMAL_TRANSACTION_ID + 1;
      43           26 : 
      44           26 :     transaction_id_precedes(xid1, xid2)
      45           21 :         && transaction_id_precedes(xid1, xid2 + pg_constants::CLOG_XACTS_PER_PAGE - 1)
      46           26 : }
      47              : 
      48              : // See SlruMayDeleteSegment() in slru.c
      49           13 : pub fn slru_may_delete_clogsegment(segpage: u32, cutoff_page: u32) -> bool {
      50           13 :     let seg_last_page = segpage + pg_constants::SLRU_PAGES_PER_SEGMENT - 1;
      51           13 : 
      52           13 :     assert_eq!(segpage % pg_constants::SLRU_PAGES_PER_SEGMENT, 0);
      53              : 
      54           13 :     clogpage_precedes(segpage, cutoff_page) && clogpage_precedes(seg_last_page, cutoff_page)
      55           13 : }
      56              : 
      57              : // Multixact utils
      58              : 
      59      1890148 : pub fn mx_offset_to_flags_offset(xid: MultiXactId) -> usize {
      60      1890148 :     ((xid / pg_constants::MULTIXACT_MEMBERS_PER_MEMBERGROUP as u32)
      61      1890148 :         % pg_constants::MULTIXACT_MEMBERGROUPS_PER_PAGE as u32
      62      1890148 :         * pg_constants::MULTIXACT_MEMBERGROUP_SIZE as u32) as usize
      63      1890148 : }
      64              : 
      65       945074 : pub fn mx_offset_to_flags_bitshift(xid: MultiXactId) -> u16 {
      66       945074 :     (xid as u16) % pg_constants::MULTIXACT_MEMBERS_PER_MEMBERGROUP
      67       945074 :         * pg_constants::MXACT_MEMBER_BITS_PER_XACT
      68       945074 : }
      69              : 
      70              : /* Location (byte offset within page) of TransactionId of given member */
      71       945074 : pub fn mx_offset_to_member_offset(xid: MultiXactId) -> usize {
      72       945074 :     mx_offset_to_flags_offset(xid)
      73       945074 :         + (pg_constants::MULTIXACT_FLAGBYTES_PER_GROUP
      74       945074 :             + (xid as u16 % pg_constants::MULTIXACT_MEMBERS_PER_MEMBERGROUP) * 4) as usize
      75       945074 : }
      76              : 
      77           60 : fn mx_offset_to_member_page(xid: u32) -> u32 {
      78           60 :     xid / pg_constants::MULTIXACT_MEMBERS_PER_PAGE as u32
      79           60 : }
      80              : 
      81           30 : pub fn mx_offset_to_member_segment(xid: u32) -> i32 {
      82           30 :     (mx_offset_to_member_page(xid) / pg_constants::SLRU_PAGES_PER_SEGMENT) as i32
      83           30 : }
      84              : 
      85              : #[cfg(test)]
      86              : mod tests {
      87              :     use super::*;
      88              : 
      89            6 :     #[test]
      90            6 :     fn test_multixid_calc() {
      91            6 :         // Check that the mx_offset_* functions produce the same values as the
      92            6 :         // corresponding PostgreSQL C macros (MXOffsetTo*). These test values
      93            6 :         // were generated by calling the PostgreSQL macros with a little C
      94            6 :         // program.
      95            6 :         assert_eq!(mx_offset_to_member_segment(0), 0);
      96            6 :         assert_eq!(mx_offset_to_member_page(0), 0);
      97            6 :         assert_eq!(mx_offset_to_flags_offset(0), 0);
      98            6 :         assert_eq!(mx_offset_to_flags_bitshift(0), 0);
      99            6 :         assert_eq!(mx_offset_to_member_offset(0), 4);
     100            6 :         assert_eq!(mx_offset_to_member_segment(1), 0);
     101            6 :         assert_eq!(mx_offset_to_member_page(1), 0);
     102            6 :         assert_eq!(mx_offset_to_flags_offset(1), 0);
     103            6 :         assert_eq!(mx_offset_to_flags_bitshift(1), 8);
     104            6 :         assert_eq!(mx_offset_to_member_offset(1), 8);
     105            6 :         assert_eq!(mx_offset_to_member_segment(123456789), 2358);
     106            6 :         assert_eq!(mx_offset_to_member_page(123456789), 75462);
     107            6 :         assert_eq!(mx_offset_to_flags_offset(123456789), 4780);
     108            6 :         assert_eq!(mx_offset_to_flags_bitshift(123456789), 8);
     109            6 :         assert_eq!(mx_offset_to_member_offset(123456789), 4788);
     110            6 :         assert_eq!(mx_offset_to_member_segment(u32::MAX - 1), 82040);
     111            6 :         assert_eq!(mx_offset_to_member_page(u32::MAX - 1), 2625285);
     112            6 :         assert_eq!(mx_offset_to_flags_offset(u32::MAX - 1), 5160);
     113            6 :         assert_eq!(mx_offset_to_flags_bitshift(u32::MAX - 1), 16);
     114            6 :         assert_eq!(mx_offset_to_member_offset(u32::MAX - 1), 5172);
     115            6 :         assert_eq!(mx_offset_to_member_segment(u32::MAX), 82040);
     116            6 :         assert_eq!(mx_offset_to_member_page(u32::MAX), 2625285);
     117            6 :         assert_eq!(mx_offset_to_flags_offset(u32::MAX), 5160);
     118            6 :         assert_eq!(mx_offset_to_flags_bitshift(u32::MAX), 24);
     119            6 :         assert_eq!(mx_offset_to_member_offset(u32::MAX), 5176);
     120            6 :     }
     121              : }
        

Generated by: LCOV version 2.1-beta