00001 /*------------------------------------------------------------------------- 00002 * 00003 * slru.h 00004 * Simple LRU buffering for transaction status logfiles 00005 * 00006 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group 00007 * Portions Copyright (c) 1994, Regents of the University of California 00008 * 00009 * src/include/access/slru.h 00010 * 00011 *------------------------------------------------------------------------- 00012 */ 00013 #ifndef SLRU_H 00014 #define SLRU_H 00015 00016 #include "access/xlogdefs.h" 00017 #include "storage/lwlock.h" 00018 00019 00020 /* 00021 * Define SLRU segment size. A page is the same BLCKSZ as is used everywhere 00022 * else in Postgres. The segment size can be chosen somewhat arbitrarily; 00023 * we make it 32 pages by default, or 256Kb, i.e. 1M transactions for CLOG 00024 * or 64K transactions for SUBTRANS. 00025 * 00026 * Note: because TransactionIds are 32 bits and wrap around at 0xFFFFFFFF, 00027 * page numbering also wraps around at 0xFFFFFFFF/xxxx_XACTS_PER_PAGE (where 00028 * xxxx is CLOG or SUBTRANS, respectively), and segment numbering at 00029 * 0xFFFFFFFF/xxxx_XACTS_PER_PAGE/SLRU_PAGES_PER_SEGMENT. We need 00030 * take no explicit notice of that fact in slru.c, except when comparing 00031 * segment and page numbers in SimpleLruTruncate (see PagePrecedes()). 00032 * 00033 * Note: slru.c currently assumes that segment file names will be four hex 00034 * digits. This sets a lower bound on the segment size (64K transactions 00035 * for 32-bit TransactionIds). 00036 */ 00037 #define SLRU_PAGES_PER_SEGMENT 32 00038 00039 /* 00040 * Page status codes. Note that these do not include the "dirty" bit. 00041 * page_dirty can be TRUE only in the VALID or WRITE_IN_PROGRESS states; 00042 * in the latter case it implies that the page has been re-dirtied since 00043 * the write started. 00044 */ 00045 typedef enum 00046 { 00047 SLRU_PAGE_EMPTY, /* buffer is not in use */ 00048 SLRU_PAGE_READ_IN_PROGRESS, /* page is being read in */ 00049 SLRU_PAGE_VALID, /* page is valid and not being written */ 00050 SLRU_PAGE_WRITE_IN_PROGRESS /* page is being written out */ 00051 } SlruPageStatus; 00052 00053 /* 00054 * Shared-memory state 00055 */ 00056 typedef struct SlruSharedData 00057 { 00058 LWLockId ControlLock; 00059 00060 /* Number of buffers managed by this SLRU structure */ 00061 int num_slots; 00062 00063 /* 00064 * Arrays holding info for each buffer slot. Page number is undefined 00065 * when status is EMPTY, as is page_lru_count. 00066 */ 00067 char **page_buffer; 00068 SlruPageStatus *page_status; 00069 bool *page_dirty; 00070 int *page_number; 00071 int *page_lru_count; 00072 LWLockId *buffer_locks; 00073 00074 /* 00075 * Optional array of WAL flush LSNs associated with entries in the SLRU 00076 * pages. If not zero/NULL, we must flush WAL before writing pages (true 00077 * for pg_clog, false for multixact, pg_subtrans, pg_notify). group_lsn[] 00078 * has lsn_groups_per_page entries per buffer slot, each containing the 00079 * highest LSN known for a contiguous group of SLRU entries on that slot's 00080 * page. 00081 */ 00082 XLogRecPtr *group_lsn; 00083 int lsn_groups_per_page; 00084 00085 /*---------- 00086 * We mark a page "most recently used" by setting 00087 * page_lru_count[slotno] = ++cur_lru_count; 00088 * The oldest page is therefore the one with the highest value of 00089 * cur_lru_count - page_lru_count[slotno] 00090 * The counts will eventually wrap around, but this calculation still 00091 * works as long as no page's age exceeds INT_MAX counts. 00092 *---------- 00093 */ 00094 int cur_lru_count; 00095 00096 /* 00097 * latest_page_number is the page number of the current end of the log; 00098 * this is not critical data, since we use it only to avoid swapping out 00099 * the latest page. 00100 */ 00101 int latest_page_number; 00102 } SlruSharedData; 00103 00104 typedef SlruSharedData *SlruShared; 00105 00106 /* 00107 * SlruCtlData is an unshared structure that points to the active information 00108 * in shared memory. 00109 */ 00110 typedef struct SlruCtlData 00111 { 00112 SlruShared shared; 00113 00114 /* 00115 * This flag tells whether to fsync writes (true for pg_clog and multixact 00116 * stuff, false for pg_subtrans and pg_notify). 00117 */ 00118 bool do_fsync; 00119 00120 /* 00121 * Decide which of two page numbers is "older" for truncation purposes. We 00122 * need to use comparison of TransactionIds here in order to do the right 00123 * thing with wraparound XID arithmetic. 00124 */ 00125 bool (*PagePrecedes) (int, int); 00126 00127 /* 00128 * Dir is set during SimpleLruInit and does not change thereafter. Since 00129 * it's always the same, it doesn't need to be in shared memory. 00130 */ 00131 char Dir[64]; 00132 } SlruCtlData; 00133 00134 typedef SlruCtlData *SlruCtl; 00135 00136 00137 extern Size SimpleLruShmemSize(int nslots, int nlsns); 00138 extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, 00139 LWLockId ctllock, const char *subdir); 00140 extern int SimpleLruZeroPage(SlruCtl ctl, int pageno); 00141 extern int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, 00142 TransactionId xid); 00143 extern int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, 00144 TransactionId xid); 00145 extern void SimpleLruWritePage(SlruCtl ctl, int slotno); 00146 extern void SimpleLruFlush(SlruCtl ctl, bool checkpoint); 00147 extern void SimpleLruTruncate(SlruCtl ctl, int cutoffPage); 00148 00149 typedef bool (*SlruScanCallback) (SlruCtl ctl, char *filename, int segpage, 00150 void *data); 00151 extern bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data); 00152 00153 /* SlruScanDirectory public callbacks */ 00154 extern bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, 00155 int segpage, void *data); 00156 extern bool SlruScanDirCbDeleteAll(SlruCtl ctl, char *filename, int segpage, 00157 void *data); 00158 00159 #endif /* SLRU_H */