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

com.netflix.exhibitor.core.index.ZooKeeperLogParser Maven / Gradle / Ivy

/*
 * Copyright 2012 Netflix, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.netflix.exhibitor.core.index;

import org.apache.jute.BinaryInputArchive;
import org.apache.jute.InputArchive;
import org.apache.jute.Record;
import org.apache.zookeeper.server.persistence.FileHeader;
import org.apache.zookeeper.server.persistence.FileTxnLog;
import org.apache.zookeeper.server.util.SerializeUtils;
import org.apache.zookeeper.txn.TxnHeader;
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.zip.Adler32;
import java.util.zip.Checksum;

public class ZooKeeperLogParser
{
    private final BinaryInputArchive logStream;
    private final boolean            validHeader;

    private static final Method             deserializeTxnMethod;
    private static final boolean            useOldDeserializeMethod;
    static
    {
        // The signature for SerializeUtils.deserializeTxn changed between 3.3.x and 3.4.x
        // so, use reflection to work with both

        Method          localSeserializeTxnMethod;
        boolean         localUseOldDeserializeMethod = true;
        try
        {
            localSeserializeTxnMethod = SerializeUtils.class.getMethod("deserializeTxn", InputArchive.class, TxnHeader.class);
        }
        catch ( Exception e )
        {
            try
            {
                localSeserializeTxnMethod = SerializeUtils.class.getMethod("deserializeTxn", byte[].class, TxnHeader.class);
                localUseOldDeserializeMethod = false;
            }
            catch ( NoSuchMethodException e1 )
            {
                throw new RuntimeException(e);
            }
        }
        deserializeTxnMethod = localSeserializeTxnMethod;
        useOldDeserializeMethod = localUseOldDeserializeMethod;
    }

    public ZooKeeperLogParser(InputStream log)
    {
        logStream = BinaryInputArchive.getArchive(log);

        boolean         localValidHeader = false;
        try
        {
            FileHeader fhdr = new FileHeader();
            fhdr.deserialize(logStream, "fileheader");
            localValidHeader = (fhdr.getMagic() == FileTxnLog.TXNLOG_MAGIC);
        }
        catch ( IOException e )
        {
            // ignore
        }
        validHeader = localValidHeader;
    }

    public boolean isValid()
    {
        return validHeader;
    }

    public void parse(LogEntryReceiver receiver) throws Exception
    {
        if ( !validHeader )
        {
            throw new Exception("Invalid magic number for");
        }

        while ( true )
        {
            long crcValue;
            byte[] bytes;
            try
            {
                crcValue = logStream.readLong("crcvalue");

                bytes = logStream.readBuffer("txnEntry");
            }
            catch ( EOFException e )
            {
                break;
            }
            if ( bytes.length == 0 )
            {
                // Since we preallocate, we define EOF to be an
                // empty transaction
                break;
            }

            Checksum crc = new Adler32();
            crc.update(bytes, 0, bytes.length);
            if ( crcValue != crc.getValue() )
            {
                throw new IOException("CRC doesn't match " + crcValue + " vs " + crc.getValue());
            }

            InputArchive    iab = BinaryInputArchive.getArchive(new ByteArrayInputStream(bytes));
            TxnHeader       hdr = new TxnHeader();

            Record          record = useOldDeserializeMethod ? (Record)deserializeTxnMethod.invoke(null, iab, hdr) : (Record)deserializeTxnMethod.invoke(null, bytes, hdr);

            if ( logStream.readByte("EOR") != 'B' )
            {
                break;  // partial transaction
            }

            receiver.receiveEntry(hdr, record);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy