/* * Initialize the Gather Merge. * * Reset data structures to ensure they're empty. Then pull at least one * tuple from leader + each worker (or set its "done" indicator), and set up * the heap. */ static void gather_merge_init(GatherMergeState *gm_state) { int nreaders = gm_state->nreaders; bool nowait = true; int i; /* Assert that gather_merge_setup made enough space */ Assert(nreaders <= castNode(GatherMerge, gm_state->ps.plan)->num_workers); /* Reset leader's tuple slot to empty */ gm_state->gm_slots[0] = NULL; /* Reset the tuple slot and tuple array for each worker */ for (i = 0; i < nreaders; i++) { /* Reset tuple array to empty */ gm_state->gm_tuple_buffers[i].nTuples = 0; gm_state->gm_tuple_buffers[i].readCounter = 0; /* Reset done flag to not-done */ gm_state->gm_tuple_buffers[i].done = false; /* Ensure output slot is empty */ ExecClearTuple(gm_state->gm_slots[i + 1]); } /* Reset binary heap to empty */ binaryheap_reset(gm_state->gm_heap); /* * First, try to read a tuple from each worker (including leader) in * nowait mode. After this, if not all workers were able to produce a * tuple (or a "done" indication), then re-read from remaining workers, * this time using wait mode. Add all live readers (those producing at * least one tuple) to the heap. */ reread: for (i = 0; i <= nreaders; i++) { CHECK_FOR_INTERRUPTS(); /* skip this source if already known done */ if ((i == 0) ? gm_state->need_to_scan_locally : !gm_state->gm_tuple_buffers[i - 1].done) { if (TupIsNull(gm_state->gm_slots[i])) { /* Don't have a tuple yet, try to get one */ if (gather_merge_readnext(gm_state, i, nowait)) binaryheap_add_unordered(gm_state->gm_heap, Int32GetDatum(i)); } else { /* * We already got at least one tuple from this worker, but * might as well see if it has any more ready by now. */ load_tuple_array(gm_state, i); } } } /* need not recheck leader, since nowait doesn't matter for it */ for (i = 1; i <= nreaders; i++) { if (!gm_state->gm_tuple_buffers[i - 1].done && TupIsNull(gm_state->gm_slots[i])) { nowait = false; goto reread; } } /* Now heapify the heap. */ binaryheap_build(gm_state->gm_heap); gm_state->gm_initialized = true; }
/* * Initialize the Gather merge tuple read. * * Pull at least a single tuple from each worker + leader and set up the heap. */ static void gather_merge_init(GatherMergeState *gm_state) { int nreaders = gm_state->nreaders; bool initialize = true; int i; /* * Allocate gm_slots for the number of worker + one more slot for leader. * Last slot is always for leader. Leader always calls ExecProcNode() to * read the tuple which will return the TupleTableSlot. Later it will * directly get assigned to gm_slot. So just initialize leader gm_slot * with NULL. For other slots below code will call * ExecInitExtraTupleSlot() which will do the initialization of worker * slots. */ gm_state->gm_slots = palloc((gm_state->nreaders + 1) * sizeof(TupleTableSlot *)); gm_state->gm_slots[gm_state->nreaders] = NULL; /* Initialize the tuple slot and tuple array for each worker */ gm_state->gm_tuple_buffers = (GMReaderTupleBuffer *) palloc0(sizeof(GMReaderTupleBuffer) * (gm_state->nreaders + 1)); for (i = 0; i < gm_state->nreaders; i++) { /* Allocate the tuple array with MAX_TUPLE_STORE size */ gm_state->gm_tuple_buffers[i].tuple = (HeapTuple *) palloc0(sizeof(HeapTuple) * MAX_TUPLE_STORE); /* Initialize slot for worker */ gm_state->gm_slots[i] = ExecInitExtraTupleSlot(gm_state->ps.state); ExecSetSlotDescriptor(gm_state->gm_slots[i], gm_state->tupDesc); } /* Allocate the resources for the merge */ gm_state->gm_heap = binaryheap_allocate(gm_state->nreaders + 1, heap_compare_slots, gm_state); /* * First, try to read a tuple from each worker (including leader) in * nowait mode, so that we initialize read from each worker as well as * leader. After this, if all active workers are unable to produce a * tuple, then re-read and this time use wait mode. For workers that were * able to produce a tuple in the earlier loop and are still active, just * try to fill the tuple array if more tuples are avaiable. */ reread: for (i = 0; i < nreaders + 1; i++) { CHECK_FOR_INTERRUPTS(); if (!gm_state->gm_tuple_buffers[i].done && (TupIsNull(gm_state->gm_slots[i]) || gm_state->gm_slots[i]->tts_isempty)) { if (gather_merge_readnext(gm_state, i, initialize)) { binaryheap_add_unordered(gm_state->gm_heap, Int32GetDatum(i)); } } else form_tuple_array(gm_state, i); } initialize = false; for (i = 0; i < nreaders; i++) if (!gm_state->gm_tuple_buffers[i].done && (TupIsNull(gm_state->gm_slots[i]) || gm_state->gm_slots[i]->tts_isempty)) goto reread; binaryheap_build(gm_state->gm_heap); gm_state->gm_initialized = true; }