Package com.yahoo.omid.replication

Source Code of com.yahoo.omid.replication.Zipper

package com.yahoo.omid.replication;

import org.jboss.netty.buffer.ChannelBuffer;

import com.yahoo.omid.tso.TSOMessage;
import com.yahoo.omid.tso.messages.AbortedTransactionReport;
import com.yahoo.omid.tso.messages.CleanedTransactionReport;
import com.yahoo.omid.tso.messages.CommittedTransactionReport;

/**
* Encodes replication messages efficiently.
*
* 1 byte msgs
*
* 00xx xxxx => commit report (commit diff = 1; startTS diff = xx xxxx)
* 010x xxxx => half abort report (startTS diff = x xxxx)
* 011x xxxx => full abort report (startTS diff = x xxxx)
*
* 2 byte msgs
*
* 10xx xxxx xxxx xxxx => commit report (ct diff = 1; st diff = xx...)
*
* Remaining msgs
*
* 11xx xxxx yyyy yyyy [yyyy yyyy ...] => header = 11xx xxxx; data = yyyy...
*
*/

public class Zipper {
   long lastStartTimestamp = 0;
   long lastCommitTimestamp = 0;

   long lastHalfAbortedTimestamp = 0;
   long lastFullAbortedTimestamp = 0;
  
   public ZipperState getZipperState() {
      return new ZipperState(lastStartTimestamp, lastCommitTimestamp, lastHalfAbortedTimestamp, lastFullAbortedTimestamp);
   }

   public void encodeCommit(ChannelBuffer buffer, long startTimestamp, long commitTimestamp) {
      long startDiff = startTimestamp - lastStartTimestamp;
      long commitDiff = commitTimestamp - lastCommitTimestamp;
      if (commitDiff == 1 && startDiff >= -32 && startDiff <= 31) {
         startDiff &= 0x3f;
         buffer.writeByte((byte) startDiff);
      } else if (commitDiff == 1 && startDiff >= -8192 && startDiff <= 8191) {
         byte high = (byte) 0x80;
         high |= (startDiff >> 8) & (byte) 0x3f;
         byte low = (byte) (startDiff & (byte) 0xff);
         buffer.writeByte(high);
         buffer.writeByte(low);
      } else if (commitDiff >= Byte.MIN_VALUE && commitDiff <= Byte.MAX_VALUE) {
         if (startDiff >= Byte.MIN_VALUE && startDiff <= Byte.MAX_VALUE) {
            buffer.writeByte(TSOMessage.CommittedTransactionReportByteByte);
            buffer.writeByte((byte) startDiff);
         } else if (startDiff >= Short.MIN_VALUE && startDiff <= Short.MAX_VALUE) {
            buffer.writeByte(TSOMessage.CommittedTransactionReportShortByte);
            buffer.writeShort((short) startDiff);
         } else if (startDiff >= Integer.MIN_VALUE && startDiff <= Integer.MAX_VALUE) {
            buffer.writeByte(TSOMessage.CommittedTransactionReportIntegerByte);
            buffer.writeInt((int) startDiff);
         } else {
            buffer.writeByte(TSOMessage.CommittedTransactionReportLongByte);
            buffer.writeLong((byte) startDiff);
         }
         buffer.writeByte((byte) commitDiff);
      } else if (commitDiff >= Short.MIN_VALUE && commitDiff <= Short.MAX_VALUE) {
         if (startDiff >= Byte.MIN_VALUE && startDiff <= Byte.MAX_VALUE) {
            buffer.writeByte(TSOMessage.CommittedTransactionReportByteShort);
            buffer.writeByte((byte) startDiff);
         } else if (startDiff >= Short.MIN_VALUE && startDiff <= Short.MAX_VALUE) {
            buffer.writeByte(TSOMessage.CommittedTransactionReportShortShort);
            buffer.writeShort((short) startDiff);
         } else if (startDiff >= Integer.MIN_VALUE && startDiff <= Integer.MAX_VALUE) {
            buffer.writeByte(TSOMessage.CommittedTransactionReportIntegerShort);
            buffer.writeInt((int) startDiff);
         } else {
            buffer.writeByte(TSOMessage.CommittedTransactionReportLongShort);
            buffer.writeLong((byte) startDiff);
         }
         buffer.writeShort((short) commitDiff);
      } else {
         buffer.writeByte(TSOMessage.CommittedTransactionReport);
         buffer.writeLong(startTimestamp);
         buffer.writeLong(commitTimestamp);
      }
      lastStartTimestamp = startTimestamp;
      lastCommitTimestamp = commitTimestamp;
   }

   public void encodeHalfAbort(ChannelBuffer buffer, long startTimestamp) {
      long diff = startTimestamp - lastHalfAbortedTimestamp;
      if (diff >= -16 && diff <= 15) {
         buffer.writeByte((byte) ((diff & 0x1f) | (0x40)));
      } else if (diff >= Byte.MIN_VALUE && diff <= Byte.MAX_VALUE) {
         buffer.writeByte(TSOMessage.AbortedTransactionReportByte);
         buffer.writeByte((byte) diff);
      } else {
         buffer.writeByte(TSOMessage.AbortedTransactionReport);
         buffer.writeLong(startTimestamp);
      }

      lastHalfAbortedTimestamp = startTimestamp;
   }

   public void encodeFullAbort(ChannelBuffer buffer, long startTimestamp) {
      long diff = startTimestamp - lastFullAbortedTimestamp;
      if (diff >= -16 && diff <= 15) {
         buffer.writeByte((byte) ((diff & 0x1f) | (0x60)));
      } else if (diff >= Byte.MIN_VALUE && diff <= Byte.MAX_VALUE) {
         buffer.writeByte(TSOMessage.CleanedTransactionReportByte);
         buffer.writeByte((byte) diff);
      } else {
         buffer.writeByte(TSOMessage.CleanedTransactionReport);
         buffer.writeLong(startTimestamp);
      }

      lastFullAbortedTimestamp = startTimestamp;
   }

   public void encodeLargestIncrease(ChannelBuffer buffer, long largestTimestamp) {
      buffer.writeByte(TSOMessage.LargestDeletedTimestampReport);
      buffer.writeLong(largestTimestamp);
   }

   public TSOMessage decodeMessage(ChannelBuffer buffer) {
      byte type = buffer.readByte();
      if ((type & 0xC0) == 0x00) { // 00xx xxxx
         return decodeCommittedTransactionReport(type, buffer);
      } else if ((type & 0xE0) == 0x40) { // 010x xxxx
         return decodeHalfAbort(type);
      } else if ((type & 0xE0) == 0x60) { // 011x xxxx
         return decodeFullAbort(type);
      } else if ((type & 0x40) == 0) { // 10xx xxxx [...]
         return decodeCommittedTransactionReport(type, buffer);
      } else if (type >= TSOMessage.CommittedTransactionReport) {
         return decodeCommittedTransactionReport(type, buffer);
      } else {
         switch (type) {
         case TSOMessage.CleanedTransactionReport:
         case TSOMessage.CleanedTransactionReportByte:
            return decodeFullAbort(type, buffer);
         case TSOMessage.AbortedTransactionReport:
         case TSOMessage.AbortedTransactionReportByte:
            return decodeHalfAbort(type, buffer);
         case TSOMessage.ZipperState:
            return decodeZipperState(buffer);
         default:
            return null;
         }
      }
   }

   private TSOMessage decodeZipperState(ChannelBuffer buffer) {
      ZipperState state = new ZipperState();
      state.readObject(buffer);
      this.lastCommitTimestamp = state.getLastCommitTimestamp();
      this.lastStartTimestamp = state.getLastStartTimestamp();
      this.lastFullAbortedTimestamp = state.getLastFullAbortedTimestamp();
      this.lastHalfAbortedTimestamp = state.getLastHalfAbortedTimestamp();
      return state;
   }

   private TSOMessage decodeHalfAbort(byte diff) {
      // Half abort
      lastHalfAbortedTimestamp += extractAbortedDifference(diff);
      return new AbortedTransactionReport(lastHalfAbortedTimestamp);
   }

   private TSOMessage decodeFullAbort(byte diff) {
      // Full abort
      lastFullAbortedTimestamp += extractAbortedDifference(diff);
      return new CleanedTransactionReport(lastFullAbortedTimestamp);
   }

   private int extractAbortedDifference(byte diff) {
      // extract the difference
      int extracted = diff & 0x1f;
      // extend the sign
      return (extracted << 27) >> 27;
   }

   private AbortedTransactionReport decodeHalfAbort(byte type, ChannelBuffer buffer) {
      AbortedTransactionReport msg;
      if (type == TSOMessage.AbortedTransactionReport) {
         msg = new AbortedTransactionReport();
         msg.readObject(buffer);
      } else {
         msg = new AbortedTransactionReport();
         int diff = buffer.readByte();
         msg.startTimestamp = lastHalfAbortedTimestamp + diff;
      }
      lastHalfAbortedTimestamp = msg.startTimestamp;

      return msg;
   }

   private CleanedTransactionReport decodeFullAbort(byte type, ChannelBuffer buffer) {
       CleanedTransactionReport msg;
      if (type == TSOMessage.CleanedTransactionReport) {
         msg = new CleanedTransactionReport();
         msg.readObject(buffer);
      } else {
         msg = new CleanedTransactionReport();
         int diff = buffer.readByte();
         msg.startTimestamp = lastFullAbortedTimestamp + diff;
      }
      lastFullAbortedTimestamp = msg.startTimestamp;

      return msg;
   }

   private CommittedTransactionReport decodeCommittedTransactionReport(byte high, ChannelBuffer aInputStream) {
      long startTimestamp = 0;
      long commitTimestamp = 0;
      if (high >= 0) {
         high = (byte) ((high << 26) >> 26);
         startTimestamp = lastStartTimestamp + high;
         commitTimestamp = lastCommitTimestamp + 1;
      } else if ((high & 0x40) == 0) {
         byte low = aInputStream.readByte();
         long startDiff = low & 0xff;
         startDiff |= ((high & 0x3f) << 26) >> 18;
         startTimestamp = lastStartTimestamp + startDiff;
         commitTimestamp = lastCommitTimestamp + 1;
      } else {
         switch (high) {
         case TSOMessage.CommittedTransactionReportByteByte:
            startTimestamp = lastStartTimestamp + aInputStream.readByte();
            commitTimestamp = lastCommitTimestamp + aInputStream.readByte();
            break;
         case TSOMessage.CommittedTransactionReportShortByte:
            startTimestamp = lastStartTimestamp + aInputStream.readShort();
            commitTimestamp = lastCommitTimestamp + aInputStream.readByte();
            break;
         case TSOMessage.CommittedTransactionReportIntegerByte:
            startTimestamp = lastStartTimestamp + aInputStream.readInt();
            commitTimestamp = lastCommitTimestamp + aInputStream.readByte();
            break;
         case TSOMessage.CommittedTransactionReportLongByte:
            startTimestamp = lastStartTimestamp + aInputStream.readLong();
            commitTimestamp = lastCommitTimestamp + aInputStream.readByte();
            break;

         case TSOMessage.CommittedTransactionReportByteShort:
            startTimestamp = lastStartTimestamp + aInputStream.readByte();
            commitTimestamp = lastCommitTimestamp + aInputStream.readShort();
            break;
         case TSOMessage.CommittedTransactionReportShortShort:
            startTimestamp = lastStartTimestamp + aInputStream.readShort();
            commitTimestamp = lastCommitTimestamp + aInputStream.readShort();
            break;
         case TSOMessage.CommittedTransactionReportIntegerShort:
            startTimestamp = lastStartTimestamp + aInputStream.readInt();
            commitTimestamp = lastCommitTimestamp + aInputStream.readShort();
            break;
         case TSOMessage.CommittedTransactionReportLongShort:
            startTimestamp = lastStartTimestamp + aInputStream.readLong();
            commitTimestamp = lastCommitTimestamp + aInputStream.readShort();
            break;
         case TSOMessage.CommittedTransactionReport:
            startTimestamp = aInputStream.readLong();
            commitTimestamp = aInputStream.readLong();
         }
      }

      lastStartTimestamp = startTimestamp;
      lastCommitTimestamp = commitTimestamp;

      return new CommittedTransactionReport(startTimestamp, commitTimestamp);
   }

}
TOP

Related Classes of com.yahoo.omid.replication.Zipper

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.