/* ---------------------------------------------------------------- * ExecSeqScanEstimate * * estimates the space required to serialize seqscan node. * ---------------------------------------------------------------- */ void ExecSeqScanEstimate(SeqScanState *node, ParallelContext *pcxt) { EState *estate = node->ss.ps.state; node->pscan_len = heap_parallelscan_estimate(estate->es_snapshot); shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len); shm_toc_estimate_keys(&pcxt->estimator, 1); }
/* ---------------------------------------------------------------- * ExecIndexOnlyScanEstimate * * Compute the amount of space we'll need in the parallel * query DSM, and inform pcxt->estimator about our needs. * ---------------------------------------------------------------- */ void ExecIndexOnlyScanEstimate(IndexOnlyScanState *node, ParallelContext *pcxt) { EState *estate = node->ss.ps.state; node->ioss_PscanLen = index_parallelscan_estimate(node->ioss_RelationDesc, estate->es_snapshot); shm_toc_estimate_chunk(&pcxt->estimator, node->ioss_PscanLen); shm_toc_estimate_keys(&pcxt->estimator, 1); }
/* ---------------------------------------------------------------- * ExecForeignScanEstimate * * Informs size of the parallel coordination information, if any * ---------------------------------------------------------------- */ void ExecForeignScanEstimate(ForeignScanState *node, ParallelContext *pcxt) { FdwRoutine *fdwroutine = node->fdwroutine; if (fdwroutine->EstimateDSMForeignScan) { node->pscan_len = fdwroutine->EstimateDSMForeignScan(node, pcxt); shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len); shm_toc_estimate_keys(&pcxt->estimator, 1); } }
void ExecCustomScanEstimate(CustomScanState *node, ParallelContext *pcxt) { const CustomExecMethods *methods = node->methods; if (methods->EstimateDSMCustomScan) { node->pscan_len = methods->EstimateDSMCustomScan(node, pcxt); shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len); shm_toc_estimate_keys(&pcxt->estimator, 1); } }
/* ---------------------------------------------------------------- * ExecBitmapHeapEstimate * * estimates the space required to serialize bitmap scan node. * ---------------------------------------------------------------- */ void ExecBitmapHeapEstimate(BitmapHeapScanState *node, ParallelContext *pcxt) { EState *estate = node->ss.ps.state; node->pscan_len = add_size(offsetof(ParallelBitmapHeapState, phs_snapshot_data), EstimateSnapshotSpace(estate->es_snapshot)); shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len); shm_toc_estimate_keys(&pcxt->estimator, 1); }
/* ---------------------------------------------------------------- * ExecSortEstimate * * Estimate space required to propagate sort statistics. * ---------------------------------------------------------------- */ void ExecSortEstimate(SortState *node, ParallelContext *pcxt) { Size size; /* don't need this if not instrumenting or no workers */ if (!node->ss.ps.instrument || pcxt->nworkers == 0) return; size = mul_size(pcxt->nworkers, sizeof(TuplesortInstrumentation)); size = add_size(size, offsetof(SharedSortInfo, sinstrument)); shm_toc_estimate_chunk(&pcxt->estimator, size); shm_toc_estimate_keys(&pcxt->estimator, 1); }
/* * Set up a dynamic shared memory segment. * * We set up a small control region that contains only a test_shm_mq_header, * plus one region per message queue. There are as many message queues as * the number of workers, plus one. */ static void setup_dynamic_shared_memory(int64 queue_size, int nworkers, dsm_segment **segp, test_shm_mq_header **hdrp, shm_mq **outp, shm_mq **inp) { shm_toc_estimator e; int i; Size segsize; dsm_segment *seg; shm_toc *toc; test_shm_mq_header *hdr; /* Ensure a valid queue size. */ if (queue_size < 0 || ((uint64) queue_size) < shm_mq_minimum_size) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("queue size must be at least %zu bytes", shm_mq_minimum_size))); if (queue_size != ((Size) queue_size)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("queue size overflows size_t"))); /* * Estimate how much shared memory we need. * * Because the TOC machinery may choose to insert padding of oddly-sized * requests, we must estimate each chunk separately. * * We need one key to register the location of the header, and we need * nworkers + 1 keys to track the locations of the message queues. */ shm_toc_initialize_estimator(&e); shm_toc_estimate_chunk(&e, sizeof(test_shm_mq_header)); for (i = 0; i <= nworkers; ++i) shm_toc_estimate_chunk(&e, (Size) queue_size); shm_toc_estimate_keys(&e, 2 + nworkers); segsize = shm_toc_estimate(&e); /* Create the shared memory segment and establish a table of contents. */ seg = dsm_create(shm_toc_estimate(&e), 0); toc = shm_toc_create(PG_TEST_SHM_MQ_MAGIC, dsm_segment_address(seg), segsize); /* Set up the header region. */ hdr = shm_toc_allocate(toc, sizeof(test_shm_mq_header)); SpinLockInit(&hdr->mutex); hdr->workers_total = nworkers; hdr->workers_attached = 0; hdr->workers_ready = 0; shm_toc_insert(toc, 0, hdr); /* Set up one message queue per worker, plus one. */ for (i = 0; i <= nworkers; ++i) { shm_mq *mq; mq = shm_mq_create(shm_toc_allocate(toc, (Size) queue_size), (Size) queue_size); shm_toc_insert(toc, i + 1, mq); if (i == 0) { /* We send messages to the first queue. */ shm_mq_set_sender(mq, MyProc); *outp = mq; } if (i == nworkers) { /* We receive messages from the last queue. */ shm_mq_set_receiver(mq, MyProc); *inp = mq; } } /* Return results to caller. */ *segp = seg; *hdrp = hdr; }