Uploaded image for project: 'WiredTiger'
  1. WiredTiger
  2. WT-5526

Remove visibility check in __wt_value_return_upd

    • Type: Icon: Improvement Improvement
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • WT10.0.0, 4.2.4, 4.3.4
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None

      The __wt_value_return_upd can be greatly simplified in durable history as we don't have birthmarks on chain and I think we no longer need to check visibility in that function. Here's the current version of the function:

      /*
       * __wt_value_return_upd --
       *     Change the cursor to reference an internal update structure return value.
       */
      int
      __wt_value_return_upd(WT_CURSOR_BTREE *cbt, WT_UPDATE *upd, bool ignore_visibility)
      {
          WT_CURSOR *cursor;
          WT_DECL_RET;
          WT_MODIFY_VECTOR modifies;
          WT_SESSION_IMPL *session;
          bool skipped_birthmark;
      
          cursor = &cbt->iface;
          session = (WT_SESSION_IMPL *)cbt->iface.session;
          __wt_modify_vector_init(session, &modifies);
      
          /*
           * We're passed a "standard" or "modified" update that's visible to us. Our caller should have
           * already checked for deleted items (we're too far down the call stack to return not-found).
           *
           * Fast path if it's a standard item, assert our caller's behavior.
           */
          if (upd->type == WT_UPDATE_STANDARD) {
              if (F_ISSET(upd, WT_UPDATE_RESTORED_FROM_DISK)) {
                  /* Copy an external update, and delete after using it */
                  WT_RET(__wt_buf_set(session, &cursor->value, upd->data, upd->size));
                  __wt_free_update_list(session, &upd);
              } else {
                  cursor->value.data = upd->data;
                  cursor->value.size = upd->size;
              }
              return (0);
          }
          WT_ASSERT(session, upd->type == WT_UPDATE_MODIFY);
      
          /*
           * Find a complete update that's visible to us, tracking modifications that are visible to us.
           */
          for (skipped_birthmark = false; upd != NULL; upd = upd->next) {
              if (upd->txnid == WT_TXN_ABORTED)
                  continue;
      
              if (!ignore_visibility && !__wt_txn_upd_visible(session, upd)) {
                  if (upd->type == WT_UPDATE_BIRTHMARK)
                      skipped_birthmark = true;
                  continue;
              }
      
              if (upd->type == WT_UPDATE_BIRTHMARK) {
                  upd = NULL;
                  break;
              }
      
              if (WT_UPDATE_DATA_VALUE(upd))
                  break;
      
              if (upd->type == WT_UPDATE_MODIFY) {
                  WT_ERR(__wt_modify_vector_push(&modifies, upd));
      
                  /*
                   * Once a modify is found, all previously committed modifications should be applied
                   * regardless of visibility.
                   */
                  ignore_visibility = true;
              }
          }
      
          /*
           * If there's no visible update and we skipped a birthmark, the base item is an empty item (in
           * other words, birthmarks we can't read act as tombstones). If there's no visible update and we
           * didn't skip a birthmark, the base item is the on-page item, which must be globally visible.
           * If there's a visible update and it's a tombstone, the base item is an empty item. If there's
           * a visible update and it's not a tombstone, the base item is the on-page item.
           */
          if (upd == NULL) {
              if (skipped_birthmark)
                  WT_ERR(__wt_buf_set(session, &cursor->value, "", 0));
              else {
                  /*
                   * Callers of this function set the cursor slot to an impossible value to check we don't
                   * try and return on-page values when the update list should have been sufficient (which
                   * happens, for example, if an update list was truncated, deleting some standard update
                   * required by a previous modify update). Assert the case.
                   */
                  WT_ASSERT(session, cbt->slot != UINT32_MAX);
      
                  WT_ERR(__value_return(cbt));
              }
          } else if (upd->type == WT_UPDATE_TOMBSTONE)
              WT_ERR(__wt_buf_set(session, &cursor->value, "", 0));
          else
              WT_ERR(__wt_buf_set(session, &cursor->value, upd->data, upd->size));
      
          /*
           * Once we have a base item, roll forward through any visible modify updates.
           */
          while (modifies.size > 0) {
              __wt_modify_vector_pop(&modifies, &upd);
              WT_ERR(__wt_modify_apply(cursor, upd->data));
          }
      
      err:
          __wt_modify_vector_free(&modifies);
          return (ret);
      }
      

            Assignee:
            chenhao.qu@mongodb.com Chenhao Qu
            Reporter:
            chenhao.qu@mongodb.com Chenhao Qu
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: