Project Name | CID | Checker | Category | Developer Description |
---|---|---|---|---|
WiredTiger | 1346885 | DEADCODE | Control flow issues | Found logically dead code that would never have been accessed. Allowing it to be removed. May never have occurred wiithout |
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 |
static int __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new, uint32_t new_entries, size_t parent_incr, bool exclusive, bool discard) { WT_DECL_ITEM(scr); WT_DECL_RET; WT_IKEY *ikey; WT_PAGE *parent; WT_PAGE_INDEX *alloc_index, *pindex; WT_REF **alloc_refp, *next_ref; WT_SPLIT_ERROR_PHASE complete; size_t parent_decr, size; uint64_t split_gen; uint32_t hint, i, j; uint32_t deleted_entries, parent_entries, result_entries; uint32_t *deleted_refs; bool empty_parent; parent = ref->home; alloc_index = pindex = NULL; parent_decr = 0; parent_entries = 0; empty_parent = false; |
<< Assigning: "complete" = "WT_ERR_RETURN".
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 |
complete = WT_ERR_RETURN; /* The parent page will be marked dirty, make sure that will succeed. */ WT_RET(__wt_page_modify_init(session, parent)); /* * We've locked the parent, which means it cannot split (which is the * only reason to worry about split generation values). */ pindex = WT_INTL_INDEX_GET_SAFE(parent); parent_entries = pindex->entries; /* * Remove any refs to deleted pages while we are splitting, we have * the internal page locked down, and are copying the refs into a new * array anyway. Switch them to the special split state, so that any * reading thread will restart. */ WT_ERR(__wt_scr_alloc(session, 10 * sizeof(uint32_t), &scr)); for (deleted_entries = 0, i = 0; i < parent_entries; ++i) { next_ref = pindex->index[i]; WT_ASSERT(session, next_ref->state != WT_REF_SPLIT); if ((discard && next_ref == ref) || (next_ref->state == WT_REF_DELETED && __wt_delete_page_skip(session, next_ref, true) && __wt_atomic_casv32( &next_ref->state, WT_REF_DELETED, WT_REF_SPLIT))) { WT_ERR(__wt_buf_grow(session, scr, (deleted_entries + 1) * sizeof(uint32_t))); deleted_refs = scr->mem; deleted_refs[deleted_entries++] = i; } } /* * The final entry count consists of the original count, plus any new * pages, less any WT_REFs we're removing (deleted entries plus the * entry we're replacing). */ result_entries = (parent_entries + new_entries) - deleted_entries; if (!discard) --result_entries; /* * If there are no remaining entries on the parent, give up, we can't * leave an empty internal page. Mark it to be evicted soon and clean * up any references that have changed state. */ if (result_entries == 0) { empty_parent = true; __wt_page_evict_soon(parent); goto err; } /* * Allocate and initialize a new page index array for the parent, then * copy references from the original index array, plus references from * the newly created split array, into place. * * Update the WT_REF's page-index hint as we go. This can race with a * thread setting the hint based on an older page-index, and the change * isn't backed out in the case of an error, so there ways for the hint * to be wrong; OK because it's just a hint. */ size = sizeof(WT_PAGE_INDEX) + result_entries * sizeof(WT_REF *); WT_ERR(__wt_calloc(session, 1, size, &alloc_index)); parent_incr += size; alloc_index->index = (WT_REF **)(alloc_index + 1); alloc_index->entries = result_entries; for (alloc_refp = alloc_index->index, hint = i = 0; i < parent_entries; ++i) { next_ref = pindex->index[i]; if (next_ref == ref) for (j = 0; j < new_entries; ++j) { ref_new[j]->home = parent; ref_new[j]->pindex_hint = hint++; *alloc_refp++ = ref_new[j]; } else if (next_ref->state != WT_REF_SPLIT) { /* Skip refs we have marked for deletion. */ next_ref->pindex_hint = hint++; *alloc_refp++ = next_ref; } } /* Check that we filled in all the entries. */ WT_ASSERT(session, alloc_refp - alloc_index->index == (ptrdiff_t)result_entries); /* Start making real changes to the tree, errors are fatal. */ complete = WT_ERR_PANIC; /* * Confirm the parent page's index hasn't moved then update it, which * makes the split visible to threads descending the tree. */ WT_ASSERT(session, WT_INTL_INDEX_GET_SAFE(parent) == pindex); WT_INTL_INDEX_SET(parent, alloc_index); alloc_index = NULL; #ifdef HAVE_DIAGNOSTIC WT_WITH_PAGE_INDEX(session, __split_verify_intl_key_order(session, parent)); #endif /* * If discarding the page's original WT_REF field, reset it to split. * Threads cursoring through the tree were blocked because that WT_REF * state was set to locked. Changing the locked state to split unblocks * those threads and causes them to re-calculate their position based * on the just-updated parent page's index. */ if (discard) { /* * Page-delete information is only read when the WT_REF state is * WT_REF_DELETED. The page-delete memory wasn't added to the * parent's footprint, ignore it here. */ if (ref->page_del != NULL) { __wt_free(session, ref->page_del->update_list); __wt_free(session, ref->page_del); } WT_PUBLISH(ref->state, WT_REF_SPLIT); } /* * Push out the changes: not required for correctness, but don't let * threads spin on incorrect page references longer than necessary. */ WT_FULL_BARRIER(); /* The split is complete and correct, ignore benign errors. */ |
<< Assigning: "complete" = "WT_ERR_IGNORE".
876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 |
complete = WT_ERR_IGNORE; /* * !!! * Swapping in the new page index released the page for eviction, we can * no longer look inside the page. */ if (ref->page == NULL) WT_ERR(__wt_verbose(session, WT_VERB_SPLIT, "%p: reverse split into parent %p, %" PRIu32 " -> %" PRIu32 " (-%" PRIu32 ")", ref->page, parent, parent_entries, result_entries, parent_entries - result_entries)); else WT_ERR(__wt_verbose(session, WT_VERB_SPLIT, "%p: split into parent %p, %" PRIu32 " -> %" PRIu32 " (+%" PRIu32 ")", ref->page, parent, parent_entries, result_entries, result_entries - parent_entries)); /* * The new page index is in place, free the WT_REF we were splitting and * any deleted WT_REFs we found, modulo the usual safe free semantics. * * Acquire a new split generation. */ split_gen = __wt_atomic_addv64(&S2C(session)->split_gen, 1); for (i = 0, deleted_refs = scr->mem; i < deleted_entries; ++i) { next_ref = pindex->index[deleted_refs[i]]; WT_ASSERT(session, next_ref->state == WT_REF_SPLIT); /* * We set the WT_REF to split, discard it, freeing any resources * it holds. * * Row-store trees where the old version of the page is being * discarded: the previous parent page's key for this child page * may have been an on-page overflow key. In that case, if the * key hasn't been deleted, delete it now, including its backing * blocks. We are exchanging the WT_REF that referenced it for * the split page WT_REFs and their keys, and there's no longer * any reference to it. Done after completing the split (if we * failed, we'd leak the underlying blocks, but the parent page * would be unaffected). */ if (parent->type == WT_PAGE_ROW_INT) { WT_TRET(__split_ovfl_key_cleanup( session, parent, next_ref)); ikey = __wt_ref_key_instantiated(next_ref); if (ikey != NULL) { size = sizeof(WT_IKEY) + ikey->size; WT_TRET(__split_safe_free( session, split_gen, exclusive, ikey, size)); parent_decr += size; } } /* * If this page was fast-truncated, any attached structure * should have been freed before now. */ WT_ASSERT(session, next_ref->page_del == NULL); WT_TRET(__wt_ref_block_free(session, next_ref)); WT_TRET(__split_safe_free( session, split_gen, exclusive, next_ref, sizeof(WT_REF))); parent_decr += sizeof(WT_REF); } /* * !!! * The original WT_REF has now been freed, we can no longer look at it. */ /* * We can't free the previous page index, there may be threads using it. * Add it to the session discard list, to be freed when it's safe. */ size = sizeof(WT_PAGE_INDEX) + pindex->entries * sizeof(WT_REF *); WT_TRET(__split_safe_free(session, split_gen, exclusive, pindex, size)); parent_decr += size; /* Adjust the parent's memory footprint and mark it dirty. */ __wt_cache_page_inmem_incr(session, parent, parent_incr); __wt_cache_page_inmem_decr(session, parent, parent_decr); __wt_page_modify_set(session, parent); err: __wt_scr_free(session, &scr); /* * A note on error handling: if we completed the split, return success, * nothing really bad can have happened, and our caller has to proceed * with the split. */ |
<< When switching on "complete", the value of "complete" must be in one of the following intervals: {[0,0], [2,2]}.
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 |
switch (complete) { case WT_ERR_RETURN: for (i = 0; i < parent_entries; ++i) { next_ref = pindex->index[i]; if (next_ref->state == WT_REF_SPLIT) next_ref->state = WT_REF_DELETED; } __wt_free_ref_index(session, NULL, alloc_index, false); /* * The split couldn't proceed because the parent would be empty, * return EBUSY so our caller knows to unlock the WT_REF that's * being deleted, but don't be noisy, there's nothing wrong. */ if (empty_parent) ret = EBUSY; break; |
<<< CID 1346885: Control flow issues DEADCODE <<< Execution cannot reach this statement: "case WT_ERR_PANIC:".
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 |
case WT_ERR_PANIC: __wt_err(session, ret, "fatal error during parent page split"); ret = WT_PANIC; break; case WT_ERR_IGNORE: if (ret != 0 && ret != WT_PANIC) { __wt_err(session, ret, "ignoring not-fatal error during parent page " "split"); ret = 0; } break; } return (ret); } /* * __split_internal -- * Split an internal page into its parent. */ static int __split_internal(WT_SESSION_IMPL *session, WT_PAGE *parent, WT_PAGE *page) { WT_BTREE *btree; WT_DECL_RET; WT_PAGE *child; WT_PAGE_INDEX *alloc_index, *child_pindex, *pindex, *replace_index; |
assignment | bt_split.c:743 | |
assignment | bt_split.c:876 | |
intervals | bt_split.c:970 | |
dead_error_condition | bt_split.c:987 | |
dead_error_begin | bt_split.c:987 |