public LinkDigest putFile(final InputStream rawBytes, final LinkDigest prevChainHead) throws IOException {
        if (mUpdates == null) {
            IOUtil.silentlyClose(rawBytes);
            throw new IllegalStateException("Not updating. Did you forget to call startUpdate?");
        }

        if (rawBytes == null) {
            throw new IllegalArgumentException("rawBytes is null");
        }

        if (prevChainHead == null) {
            throw new IllegalArgumentException("prevChainHead is null");
        }

        InputStream prevStream = null; // Leaving this null causes a full reinsert.
        try {
            if (!prevChainHead.isNullDigest() &&
                mLinkMap.getChain(prevChainHead, true).size() < MAX_CHAIN_LENGTH) {
                // Add to chain the existing chain.
                prevStream = getFile(prevChainHead);
            }

            final HistoryLink link = mCoder.makeDelta(mLinkDataFactory,
                                                      prevChainHead,
                                                      prevStream,
                                                      rawBytes,
                                                      false);

            mUpdates.append(link.mHash);
            mLinkMap.addLink(link);

            return link.mHash;

        } finally {
            IOUtil.silentlyClose(rawBytes);
            IOUtil.silentlyClose(prevStream);
        }
    }