private int replaceValue(Key key, ValueHelper valueHelper, int p) {
        int kbData = getInt(p);
        int tail = decodeKeyBlockTail(kbData);
        int tbData = getInt(tail);
        int klength = decodeTailBlockKLength(tbData);
        int oldTailSize = decodeTailBlockSize(tbData);
        boolean wasMVV = false;
        boolean isMVV = false;

        int length;
        if (isIndexPage()) {
            length = 0;
        } else {
            length = valueHelper.requiredLength(_bytes, tail + _tailHeaderSize + klength, oldTailSize - _tailHeaderSize
                    - klength);
            wasMVV = isValueMVV(_bytes, tail + _tailHeaderSize + klength, oldTailSize - _tailHeaderSize - klength);
        }

        int newTailSize = klength + length + _tailHeaderSize;
        int oldNext = (tail + oldTailSize + ~TAILBLOCK_MASK) & TAILBLOCK_MASK;
        int newNext = (tail + newTailSize + ~TAILBLOCK_MASK) & TAILBLOCK_MASK;
        int newTail = tail;
        if (newNext < oldNext) {
            // Free the remainder of the old tail block
            deallocTail(newNext, oldNext - newNext);
        } else if (newNext > oldNext) {
            if (!willFit(newNext - oldNext)) {
                return -1; // need to split the page
            }
            //
            // Free the old tail block entirely
            //
            deallocTail(tail, oldTailSize);
            newTail = allocTail(newTailSize);
            if (newTail == -1) {
                repack();
                //
                // Guaranteed to succeed because of the test on willFit() above
                //
                newTail = allocTail(newTailSize);
                if (newTail == -1) {
                    _persistit.fatal("Insufficient space to replace records in " + this + " at =" + p, null);
                }
            }
            putInt(p, encodeKeyBlockTail(kbData, newTail));
        }
        putInt(newTail, encodeTailBlock(newTailSize, klength));
        if (newTail != tail) {
            System.arraycopy(key.getEncodedBytes(), key.getEncodedSize() - klength, _bytes, newTail + _tailHeaderSize,
                    klength);
        }

        if (isIndexPage()) {
            long pointer = valueHelper.getPointerValue();
            Debug.$assert0.t(p + KEYBLOCK_LENGTH < _keyBlockEnd ? pointer > 0 : pointer == -1);
            putInt(newTail + TAILBLOCK_POINTER, (int) pointer);
        } else {
            final int storedLength = valueHelper.storeVersion(_bytes, newTail + _tailHeaderSize + klength, oldTailSize
                    - _tailHeaderSize - klength, _bytes.length); // TODO - limit
            isMVV = isValueMVV(_bytes, newTail + _tailHeaderSize + klength, storedLength & MVV.STORE_LENGTH_MASK);
        }
        if (!wasMVV && isMVV) {
            _mvvCount++;
        } else if (wasMVV && !isMVV) {
            _mvvCount--;
        }
        if (Debug.ENABLED) {
            assertVerify();
        }
        return p | (key.getEncodedSize() << DEPTH_SHIFT) | EXACT_MASK;
    }