private static AsyncDiskEntry basicUpdate(DiskEntry entry, InternalRegion region,
        @Unretained Object newValue, EntryEventImpl event) throws RegionClearedException {
      AsyncDiskEntry result = null;
      DiskRegion dr = region.getDiskRegion();
      DiskId did = entry.getDiskId();
      Token oldValue;
      int oldValueLength;
      oldValue = entry.getValueAsToken();
      if (Token.isRemovedFromDisk(newValue)) {
        if (dr.isBackup()) {
          dr.testIsRecoveredAndClear(did);
        }
        boolean caughtCacheClosed = false;
        try {
          if (!Token.isRemovedFromDisk(oldValue)) {
            result = basicRemoveFromDisk(entry, region, false);
          }
        } catch (CacheClosedException e) {
          caughtCacheClosed = true;
          throw e;
        } finally {
          // do not to set the value to be removedFromDisk since it failed to persist
          if (!caughtCacheClosed) {
            // Ensure that the value is rightly set despite clear so
            // that it can be distributed correctly
            entry.setValueWithContext(region, newValue); // OFFHEAP newValue was already
                                                         // preparedForCache
          }
        }
      } else if (newValue instanceof RecoveredEntry) {
        ((RecoveredEntry) newValue).applyToDiskEntry(entry, region, dr, did);
      } else {
        boolean newValueStoredInEntry = false;
        try {
          // The new value in the entry needs to be set after the disk writing
          // has succeeded.
          if (did != null && did.isPendingAsync()) {
            // if the entry was not yet written to disk, we didn't update
            // the bytes on disk.
            oldValueLength = 0;
          } else {
            oldValueLength = getValueLength(did);
          }

          if (dr.isBackup()) {
            dr.testIsRecoveredAndClear(did);
            if (doSynchronousWrite(region, dr)) {
              if (AbstractRegionEntry.isCompressible(dr, newValue)) {
                // In case of compression the value is being set first
                // so that writeToDisk can get it back from the entry
                // decompressed if it does not have it already in the event.
                // TODO: this may have introduced a bug with clear since
                // writeToDisk can throw RegionClearedException which
                // was supposed to stop us from changing entry.
                newValueStoredInEntry = true;
                entry.setValueWithContext(region, newValue); // OFFHEAP newValue already prepared
                // newValue is prepared and compressed. We can't write compressed values to disk.
                if (!entry.isRemovedFromDisk()) {
                  writeToDisk(entry, region, false, event);
                }
              } else {
                writeBytesToDisk(entry, region, false, createValueWrapper(newValue, event));
                newValueStoredInEntry = true;
                entry.setValueWithContext(region, newValue); // OFFHEAP newValue already prepared
              }

            } else {
              // If we have concurrency checks enabled for a persistent region, we need
              // to add an entry to the async queue for every update to maintain the RVV
              boolean maintainRVV = region.getConcurrencyChecksEnabled();

              if (!did.isPendingAsync() || maintainRVV) {
                // if the entry is not async, we need to schedule it
                // for regions with concurrency checks enabled, we add an entry
                // to the queue for every entry.
                did.setPendingAsync(true);
                VersionTag tag = null;
                VersionStamp stamp = entry.getVersionStamp();
                if (stamp != null) {
                  tag = stamp.asVersionTag();
                }
                result = new AsyncDiskEntry(region, entry, tag);
              }
              newValueStoredInEntry = true;
              entry.setValueWithContext(region, newValue); // OFFHEAP newValue already prepared
            }
          } else if (did != null) {
            newValueStoredInEntry = true;
            entry.setValueWithContext(region, newValue); // OFFHEAP newValue already prepared

            // Mark the id as needing to be written
            // The disk remove that this section used to do caused bug 30961
            // @todo this seems wrong. How does leaving it on disk fix the bug?
            did.markForWriting();
          } else {
            newValueStoredInEntry = true;
            entry.setValueWithContext(region, newValue);
          }
        } finally {
          if (!newValueStoredInEntry) {
            OffHeapHelper.release(newValue);
          }
        }


        if (Token.isInvalidOrRemoved(newValue)) {
          if (oldValue == null) {
            updateStats(dr, region, 0/* InVM */, -1/* OnDisk */, -oldValueLength);
          } else if (!Token.isInvalidOrRemoved(oldValue)) {
            updateStats(dr, region, -1/* InVM */, 0/* OnDisk */, 0);
          } else {
            // oldValue was also a token which is neither in vm or on disk.
          }
        } else { // we have a value to put in the vm
          if (oldValue == null) {
            updateStats(dr, region, 1/* InVM */, -1/* OnDisk */, -oldValueLength);
          } else if (Token.isInvalidOrRemoved(oldValue)) {
            updateStats(dr, region, 1/* InVM */, 0/* OnDisk */, 0/* overflowBytesOnDisk */);
          } else {
            // old value was also in vm so no change
          }
        }
      }
      if (entry instanceof EvictableEntry) {
        EvictableEntry le = (EvictableEntry) entry;
        le.unsetEvicted();
      }
      return result;
    }
Updates the value of the disk entry with a new value. This allows us to free up disk space in
the non-backup case.
geode-core/src/main/java/org/apache/geode/internal/cache/entries/DiskEntry.java