Package com.alimama.mdrill.editlog.read

Source Code of com.alimama.mdrill.editlog.read.FSEditLogOp$Writer

package com.alimama.mdrill.editlog.read;


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.HashMap;
import java.util.zip.CheckedInputStream;
import java.util.zip.Checksum;

import com.alimama.mdrill.editlog.AddOp;
import com.alimama.mdrill.editlog.defined.FSEditLogOpCodes;
import com.alimama.mdrill.editlog.defined.HdfsConstants;
import com.alimama.mdrill.editlog.util.PureJavaCrc32;
import com.alimama.mdrill.editlog.write.DataOutputBuffer;
import com.google.common.base.Preconditions;


public abstract class FSEditLogOp {
  public final FSEditLogOpCodes opCode;
  public long txid;
  final public static class OpInstanceCache {
    private HashMap<FSEditLogOpCodes, FSEditLogOp> inst =  new HashMap<FSEditLogOpCodes, FSEditLogOp>();
    public OpInstanceCache() {
      inst.put(FSEditLogOpCodes.OP_ADD, new AddOp());
    }
   
    public FSEditLogOp get(FSEditLogOpCodes opcode) {
      return inst.get(opcode);
    }
  }

  protected FSEditLogOp(FSEditLogOpCodes opCode) {
    this.opCode = opCode;
    this.txid = HdfsConstants.INVALID_TXID;
  }

  public long getTransactionId() {
    Preconditions.checkState(txid != HdfsConstants.INVALID_TXID);
    return txid;
  }

  public String getTransactionIdStr() {
    return (txid == HdfsConstants.INVALID_TXID) ? "(none)" : "" + txid;
  }
 
  public boolean hasTransactionId() {
    return (txid != HdfsConstants.INVALID_TXID);
  }

  public void setTransactionId(long txid) {
    this.txid = txid;
  }
 


  public abstract void readFields(DataInputStream in, int logVersion)
      throws IOException;

  public abstract void writeFields(DataOutputStream out)
      throws IOException;

  public static class Writer {
    private final DataOutputBuffer buf;
    private final Checksum checksum;

    public Writer(DataOutputBuffer out) {
      this.buf = out;
      this.checksum = new PureJavaCrc32();
    }

    public void writeOp(FSEditLogOp op) throws IOException {
      int start = buf.getLength();
      buf.writeByte(op.opCode.getOpCode());
      buf.writeLong(op.txid);
      op.writeFields(buf);
      int end = buf.getLength();
      checksum.reset();
      checksum.update(buf.getData(), start, end-start);
      int sum = (int)checksum.getValue();
      buf.writeInt(sum);
    }
  }

  public static class Reader {
    private final DataInputStream in;
    private final int logVersion;
    private final Checksum checksum;
    private final OpInstanceCache cache;
    private int maxOpSize;

    public Reader(DataInputStream in,int logVersion,int maxOpSize) {
      this.logVersion = logVersion;
      this.checksum = new PureJavaCrc32();
      this.in = new DataInputStream(new CheckedInputStream(in, this.checksum));
      this.cache = new OpInstanceCache();
      this.maxOpSize = maxOpSize;
    }

    public void setMaxOpSize(int maxOpSize) {
      this.maxOpSize = maxOpSize;
    }

    public FSEditLogOp readOp(boolean skipBrokenEdits) throws IOException {

        try {
          return decodeOp();
        }
        catch (IOException e) {
          if (!skipBrokenEdits) {
            throw e;
          }else{
            return null;
          }
        } catch (RuntimeException e) {
          if (!skipBrokenEdits) {
            throw e;
          }else{
            return null;
          }
        } catch (Throwable e) {
          if (!skipBrokenEdits) {
            throw new IOException("got unexpected exception " +
                e.getMessage(), e);
          }else{
            return null;
          }
        }
    }



    private FSEditLogOp decodeOp() throws IOException {
      in.mark(maxOpSize);

      checksum.reset();


      byte opCodeByte;
      try {
        opCodeByte = in.readByte();
      } catch (EOFException eof) {
        // EOF at an opcode boundary is expected.
        return null;
      }

      FSEditLogOpCodes opCode = FSEditLogOpCodes.fromByte(opCodeByte);
      if (opCode == FSEditLogOpCodes.OP_INVALID) {
          throw new IOException("Read invalid opcode " + opCode);
      }

      FSEditLogOp op = cache.get(opCode);
      if (op == null) {
        throw new IOException("Read invalid opcode " + opCode);
      }

      op.setTransactionId(in.readLong());
      op.readFields(in, logVersion);
      validateChecksum(in, checksum, op.txid);
      return op;
    }

    /**
     * Validate a transaction's checksum
     */
    private void validateChecksum(DataInputStream in,
                                  Checksum checksum,
                                  long txid)
        throws IOException {

        int calculatedChecksum = (int)checksum.getValue();
        int readChecksum = in.readInt(); // read in checksum
        if (readChecksum != calculatedChecksum) {
          throw new IOException(
              "Transaction is corrupt. Calculated checksum is " +
              calculatedChecksum + " but read checksum " + readChecksum+",txid="+txid);
        }
    }
  }

}

TOP

Related Classes of com.alimama.mdrill.editlog.read.FSEditLogOp$Writer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.