All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.je.log.ChecksumValidator Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.je.log;

import java.nio.ByteBuffer;
import java.util.zip.Checksum;

import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.utilint.Adler32;
import com.sleepycat.je.utilint.DbLsn;

/**
 * Checksum validator is used to check checksums on log entries.
 */
public class ChecksumValidator {
    private static final boolean DEBUG = false;

    private final EnvironmentImpl envImpl;
    private Checksum cksum;

    public ChecksumValidator(final EnvironmentImpl envImpl) {
        this.envImpl = envImpl;
        cksum = Adler32.makeChecksum();
    }

    public void reset() {
        cksum.reset();
    }

    /**
     * Add this byte buffer to the checksum. Assume the byte buffer is already
     * positioned at the data.
     * @param buf target buffer
     * @param length of data
     */
    public void update(ByteBuffer buf, int length)
        throws ChecksumException {

        if (buf == null) {
            throw new ChecksumException(
                "null buffer given to checksum validation, probably " +
                 " result of 0's in log file, len=" + length);
        }

        int bufStart = buf.position();

        if (DEBUG) {
            System.out.println("bufStart = " + bufStart +
                               " length = " + length);
        }

        update(buf.array(), bufStart + buf.arrayOffset(), length);
    }

    public void update(byte[] buf, int offset, int length) {
        cksum.update(buf, offset, length);
    }

    void validate(long expectedChecksum, long lsn)
        throws ChecksumException {

        if (expectedChecksum != cksum.getValue()) {

            /*
             * Check for erased log entry before throwing ChecksumException.
             * This handles the following reader scenario:
             * 1. Reader thread reads the header. The entry type is not
             *    LOG_ERASED, so checksum verification proceeds.
             * 2. Eraser thread erases the entry.
             * 3. Reader thread reads the rest of the log entry, which was
             *    overwritten in step 2. The erased data is used to update
             *    the checksum.
             * 4. Reader thread calls this method and checksum verification
             *    fails.
             */
            if (envImpl.getDataEraser().isEntryErased(lsn)) {
                return;
            }

            throw new ChecksumException
                ("Location " + DbLsn.getNoFormatString(lsn) +
                 " expected " + expectedChecksum + " got " + cksum.getValue());
        }
    }

    public void validate(long expectedChecksum, long fileNum, long fileOffset)
        throws ChecksumException {

        validate(expectedChecksum, DbLsn.makeLsn(fileNum, fileOffset));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy