* cache_store_tuple * Add the tuple stored in 'slot' to the mstate's current cache entry. * The cache entry must have already been made with cache_lookup(). * mstate's last_tuple field must point to the tail of mstate->entry's * list of tuples. */
| 593 | * list of tuples. |
| 594 | */ |
| 595 | static bool |
| 596 | cache_store_tuple(MemoizeState *mstate, TupleTableSlot *slot) |
| 597 | { |
| 598 | MemoizeTuple *tuple; |
| 599 | MemoizeEntry *entry = mstate->entry; |
| 600 | MemoryContext oldcontext; |
| 601 | |
| 602 | Assert(slot != NULL); |
| 603 | Assert(entry != NULL); |
| 604 | |
| 605 | oldcontext = MemoryContextSwitchTo(mstate->tableContext); |
| 606 | |
| 607 | tuple = (MemoizeTuple *) palloc(sizeof(MemoizeTuple)); |
| 608 | tuple->mintuple = ExecCopySlotMinimalTuple(slot); |
| 609 | tuple->next = NULL; |
| 610 | |
| 611 | /* Account for the memory we just consumed */ |
| 612 | mstate->mem_used += CACHE_TUPLE_BYTES(tuple); |
| 613 | |
| 614 | if (entry->tuplehead == NULL) |
| 615 | { |
| 616 | /* |
| 617 | * This is the first tuple for this entry, so just point the list head |
| 618 | * to it. |
| 619 | */ |
| 620 | entry->tuplehead = tuple; |
| 621 | } |
| 622 | else |
| 623 | { |
| 624 | /* push this tuple onto the tail of the list */ |
| 625 | mstate->last_tuple->next = tuple; |
| 626 | } |
| 627 | |
| 628 | mstate->last_tuple = tuple; |
| 629 | MemoryContextSwitchTo(oldcontext); |
| 630 | |
| 631 | /* |
| 632 | * If we've gone over our memory budget then free up some space in the |
| 633 | * cache. |
| 634 | */ |
| 635 | if (mstate->mem_used > mstate->mem_limit) |
| 636 | { |
| 637 | MemoizeKey *key = entry->key; |
| 638 | |
| 639 | if (!cache_reduce_memory(mstate, key)) |
| 640 | return false; |
| 641 | |
| 642 | /* |
| 643 | * The process of removing entries from the cache may have caused the |
| 644 | * code in simplehash.h to shuffle elements to earlier buckets in the |
| 645 | * hash table. If it has, we'll need to find the entry again by |
| 646 | * performing a lookup. Fortunately, we can detect if this has |
| 647 | * happened by seeing if the entry is still in use and that the key |
| 648 | * pointer matches our expected key. |
| 649 | */ |
| 650 | if (entry->status != memoize_SH_IN_USE || entry->key != key) |
| 651 | { |
| 652 | /* |
no test coverage detected