PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
syncscan.c File Reference
#include "postgres.h"
#include "access/heapam.h"
#include "miscadmin.h"
#include "storage/lwlock.h"
#include "storage/shmem.h"
#include "utils/rel.h"
Include dependency graph for syncscan.c:

Go to the source code of this file.

Data Structures

struct  ss_scan_location_t
 
struct  ss_lru_item_t
 
struct  ss_scan_locations_t
 

Macros

#define SYNC_SCAN_NELEM   20
 
#define SYNC_SCAN_REPORT_INTERVAL   (128 * 1024 / BLCKSZ)
 
#define SizeOfScanLocations(N)   (offsetof(ss_scan_locations_t, items) + (N) * sizeof(ss_lru_item_t))
 

Typedefs

typedef struct ss_scan_location_t ss_scan_location_t
 
typedef struct ss_lru_item_t ss_lru_item_t
 
typedef struct ss_scan_locations_t ss_scan_locations_t
 

Functions

static BlockNumber ss_search (RelFileNode relfilenode, BlockNumber location, bool set)
 
Size SyncScanShmemSize (void)
 
void SyncScanShmemInit (void)
 
BlockNumber ss_get_location (Relation rel, BlockNumber relnblocks)
 
void ss_report_location (Relation rel, BlockNumber location)
 

Variables

static ss_scan_locations_tscan_locations
 

Macro Definition Documentation

#define SizeOfScanLocations (   N)    (offsetof(ss_scan_locations_t, items) + (N) * sizeof(ss_lru_item_t))

Definition at line 111 of file syncscan.c.

Referenced by SyncScanShmemInit(), and SyncScanShmemSize().

#define SYNC_SCAN_NELEM   20

Definition at line 71 of file syncscan.c.

Referenced by SyncScanShmemInit(), and SyncScanShmemSize().

#define SYNC_SCAN_REPORT_INTERVAL   (128 * 1024 / BLCKSZ)

Definition at line 83 of file syncscan.c.

Referenced by ss_report_location().

Typedef Documentation

Function Documentation

BlockNumber ss_get_location ( Relation  rel,
BlockNumber  relnblocks 
)

Definition at line 253 of file syncscan.c.

References elog, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), RelationData::rd_node, RelationGetRelationName, and ss_search().

Referenced by heap_parallelscan_nextpage(), and initscan().

254 {
255  BlockNumber startloc;
256 
257  LWLockAcquire(SyncScanLock, LW_EXCLUSIVE);
258  startloc = ss_search(rel->rd_node, 0, false);
259  LWLockRelease(SyncScanLock);
260 
261  /*
262  * If the location is not a valid block number for this scan, start at 0.
263  *
264  * This can happen if for instance a VACUUM truncated the table since the
265  * location was saved.
266  */
267  if (startloc >= relnblocks)
268  startloc = 0;
269 
270 #ifdef TRACE_SYNCSCAN
271  if (trace_syncscan)
272  elog(LOG,
273  "SYNC_SCAN: start \"%s\" (size %u) at %u",
274  RelationGetRelationName(rel), relnblocks, startloc);
275 #endif
276 
277  return startloc;
278 }
static BlockNumber ss_search(RelFileNode relfilenode, BlockNumber location, bool set)
Definition: syncscan.c:191
uint32 BlockNumber
Definition: block.h:31
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define RelationGetRelationName(relation)
Definition: rel.h:433
RelFileNode rd_node
Definition: rel.h:85
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
#define elog
Definition: elog.h:219
void ss_report_location ( Relation  rel,
BlockNumber  location 
)

Definition at line 288 of file syncscan.c.

References elog, LOG, LW_EXCLUSIVE, LWLockConditionalAcquire(), LWLockRelease(), RelationData::rd_node, RelationGetRelationName, ss_search(), and SYNC_SCAN_REPORT_INTERVAL.

Referenced by heap_parallelscan_nextpage(), heapgettup(), heapgettup_pagemode(), and tablesample_getnext().

289 {
290 #ifdef TRACE_SYNCSCAN
291  if (trace_syncscan)
292  {
293  if ((location % 1024) == 0)
294  elog(LOG,
295  "SYNC_SCAN: scanning \"%s\" at %u",
296  RelationGetRelationName(rel), location);
297  }
298 #endif
299 
300  /*
301  * To reduce lock contention, only report scan progress every N pages. For
302  * the same reason, don't block if the lock isn't immediately available.
303  * Missing a few updates isn't critical, it just means that a new scan
304  * that wants to join the pack will start a little bit behind the head of
305  * the scan. Hopefully the pages are still in OS cache and the scan
306  * catches up quickly.
307  */
308  if ((location % SYNC_SCAN_REPORT_INTERVAL) == 0)
309  {
310  if (LWLockConditionalAcquire(SyncScanLock, LW_EXCLUSIVE))
311  {
312  (void) ss_search(rel->rd_node, location, true);
313  LWLockRelease(SyncScanLock);
314  }
315 #ifdef TRACE_SYNCSCAN
316  else if (trace_syncscan)
317  elog(LOG,
318  "SYNC_SCAN: missed update for \"%s\" at %u",
319  RelationGetRelationName(rel), location);
320 #endif
321  }
322 }
static BlockNumber ss_search(RelFileNode relfilenode, BlockNumber location, bool set)
Definition: syncscan.c:191
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1282
#define RelationGetRelationName(relation)
Definition: rel.h:433
RelFileNode rd_node
Definition: rel.h:85
#define elog
Definition: elog.h:219
#define SYNC_SCAN_REPORT_INTERVAL
Definition: syncscan.c:83
static BlockNumber ss_search ( RelFileNode  relfilenode,
BlockNumber  location,
bool  set 
)
static

Definition at line 191 of file syncscan.c.

References ss_scan_locations_t::head, ss_scan_location_t::location, ss_lru_item_t::location, ss_lru_item_t::next, NULL, ss_lru_item_t::prev, ss_scan_location_t::relfilenode, RelFileNodeEquals, and ss_scan_locations_t::tail.

Referenced by ss_get_location(), and ss_report_location().

192 {
193  ss_lru_item_t *item;
194 
195  item = scan_locations->head;
196  for (;;)
197  {
198  bool match;
199 
200  match = RelFileNodeEquals(item->location.relfilenode, relfilenode);
201 
202  if (match || item->next == NULL)
203  {
204  /*
205  * If we reached the end of list and no match was found, take over
206  * the last entry
207  */
208  if (!match)
209  {
210  item->location.relfilenode = relfilenode;
211  item->location.location = location;
212  }
213  else if (set)
214  item->location.location = location;
215 
216  /* Move the entry to the front of the LRU list */
217  if (item != scan_locations->head)
218  {
219  /* unlink */
220  if (item == scan_locations->tail)
221  scan_locations->tail = item->prev;
222  item->prev->next = item->next;
223  if (item->next)
224  item->next->prev = item->prev;
225 
226  /* link */
227  item->prev = NULL;
228  item->next = scan_locations->head;
229  scan_locations->head->prev = item;
230  scan_locations->head = item;
231  }
232 
233  return item->location.location;
234  }
235 
236  item = item->next;
237  }
238 
239  /* not reached */
240 }
RelFileNode relfilenode
Definition: syncscan.c:93
ss_scan_location_t location
Definition: syncscan.c:101
BlockNumber location
Definition: syncscan.c:94
ss_lru_item_t * head
Definition: syncscan.c:106
ss_lru_item_t * tail
Definition: syncscan.c:107
#define NULL
Definition: c.h:226
struct ss_lru_item_t * next
Definition: syncscan.c:100
static ss_scan_locations_t * scan_locations
Definition: syncscan.c:115
struct ss_lru_item_t * prev
Definition: syncscan.c:99
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88
void SyncScanShmemInit ( void  )

Definition at line 135 of file syncscan.c.

References Assert, RelFileNode::dbNode, ss_scan_locations_t::head, i, InvalidBlockNumber, InvalidOid, IsUnderPostmaster, ss_scan_locations_t::items, ss_scan_location_t::location, ss_lru_item_t::location, ss_lru_item_t::next, NULL, ss_lru_item_t::prev, ss_scan_location_t::relfilenode, RelFileNode::relNode, ShmemInitStruct(), SizeOfScanLocations, RelFileNode::spcNode, SYNC_SCAN_NELEM, and ss_scan_locations_t::tail.

Referenced by CreateSharedMemoryAndSemaphores().

136 {
137  int i;
138  bool found;
139 
141  ShmemInitStruct("Sync Scan Locations List",
143  &found);
144 
145  if (!IsUnderPostmaster)
146  {
147  /* Initialize shared memory area */
148  Assert(!found);
149 
152 
153  for (i = 0; i < SYNC_SCAN_NELEM; i++)
154  {
155  ss_lru_item_t *item = &scan_locations->items[i];
156 
157  /*
158  * Initialize all slots with invalid values. As scans are started,
159  * these invalid entries will fall off the LRU list and get
160  * replaced with real entries.
161  */
166 
167  item->prev = (i > 0) ?
168  (&scan_locations->items[i - 1]) : NULL;
169  item->next = (i < SYNC_SCAN_NELEM - 1) ?
170  (&scan_locations->items[i + 1]) : NULL;
171  }
172  }
173  else
174  Assert(found);
175 }
#define SYNC_SCAN_NELEM
Definition: syncscan.c:71
RelFileNode relfilenode
Definition: syncscan.c:93
ss_scan_location_t location
Definition: syncscan.c:101
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
ss_lru_item_t items[FLEXIBLE_ARRAY_MEMBER]
Definition: syncscan.c:108
BlockNumber location
Definition: syncscan.c:94
bool IsUnderPostmaster
Definition: globals.c:100
ss_lru_item_t * head
Definition: syncscan.c:106
ss_lru_item_t * tail
Definition: syncscan.c:107
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define InvalidBlockNumber
Definition: block.h:33
struct ss_lru_item_t * next
Definition: syncscan.c:100
int i
static ss_scan_locations_t * scan_locations
Definition: syncscan.c:115
struct ss_lru_item_t * prev
Definition: syncscan.c:99
#define SizeOfScanLocations(N)
Definition: syncscan.c:111
Size SyncScanShmemSize ( void  )

Definition at line 126 of file syncscan.c.

References SizeOfScanLocations, and SYNC_SCAN_NELEM.

Referenced by CreateSharedMemoryAndSemaphores().

127 {
129 }
#define SYNC_SCAN_NELEM
Definition: syncscan.c:71
#define SizeOfScanLocations(N)
Definition: syncscan.c:111

Variable Documentation

ss_scan_locations_t* scan_locations
static

Definition at line 115 of file syncscan.c.