Package com.cloudhopper.mq.message

Source Code of com.cloudhopper.mq.message.PriorityMQMessage$Key

package com.cloudhopper.mq.message;

/*
* #%L
* ch-mq
* %%
* Copyright (C) 2012 Cloudhopper by Twitter
* %%
* 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.
* #L%
*/

import java.nio.ByteBuffer;
import com.cloudhopper.mq.util.Priority;
import com.cloudhopper.mq.util.Tiny;

/**
* Implementation of an MQMessage that includes Priority. For use with priority queues.
*
* @author garth
*/
public class PriorityMQMessage<T> extends AttemptCountingMQMessage<T> implements Comparable<PriorityMQMessage> {

    public PriorityMQMessage() {
  super();
    }

    public PriorityMQMessage(Priority priority, T body) {
  super();
  this.priority = priority;
  this.body = body;;
    }

    public PriorityMQMessage(short transferAttempts,
           short transfers,
           String logItemIdentifier,
           Priority priority) {
  super(transferAttempts, transfers, logItemIdentifier);
  this.priority = priority;
    }

    public PriorityMQMessage(short transferAttempts,
           short transfers,
           String logItemIdentifier,
           Priority priority,
           long ts,
           int sequence) {
  super(transferAttempts, transfers, logItemIdentifier);
  setPriority(priority);
  //TODO: need to rethink this. allowing external setting of the sequence means that we may have
  //      colliding keys (e.g. when decoding messages from 2 different remote brokers)
  setSequence(sequence);
  setTimestamp(ts);
    }

    private Priority priority;
    private Tiny sequence = new Tiny(0);
    private long ts = 0L;
    private static final long SIX_BYTE_LONG = 140737488355328L;

    /**
     * For priority messaging, if the message should be treated as a
     * "first in line" priority message. Actual algorithm for priority is
     * left up to the queue implementation.
     */
    public Priority getPriority() {
  return this.priority;
    }

    /**
     * Sets the priority of the message.
     */
    public void setPriority(Priority priority) {
  this.priority = priority;
    }

    /**
     * Gets the timestamp of the message
     */
    public long getTimestamp() {
  return this.ts;
    }

    /**
     * Set the timestamp of the message when it was created. Doesn't allow longs greater than 6 bytes
     */
    public void setTimestamp(long ts) {
  if (ts > SIX_BYTE_LONG || ts < 0) throw new IllegalArgumentException("Ts must be 0-140737488355328");
  this.ts = ts;
    }

    /**
     * Gets the sequence number
     */
    public int getSequence() {
  return this.sequence.intValue();
    }

    /**
     * Sets the sequence number. Will throw an IllegalArgumentException for values > 255
     */
    public void setSequence(int seq) {
  this.sequence = new Tiny(seq);
    }

    //////////////////////////////////////
    //
    // Utilities for DefaultPriorityQueue
    // these values are not persisted
    //
    //////////////////////////////////////

    public boolean isTimestampSet() {
  return (this.ts > 0);
    }

    public boolean isSequenceSet() {
  return (this.sequence != null);
    }

    // TODO: use inner class Key below
    public long key() {
  byte[] k = new byte[8];
  ByteBuffer buf = ByteBuffer.wrap(k);
  buf.put(priority.byteValue());
        for (int i = 0; i < 6; i++) {
            buf.put( (byte)(ts >>> ((6-1-i) * 8)) );
        }
  buf.put(sequence.byteValue());
  return ByteBuffer.wrap(k).getLong();
    }

    /**
     * Compares priority of two PriorityMQMessage, first by priority, then by key (ts+seq).
     */
    @Override public int compareTo(PriorityMQMessage o) {
  int diff = getPriority().intValue() - o.getPriority().intValue();
  if (diff == 0) {
      long sdiff = key() - o.key();
      if (sdiff > 0) return 1;
      else if (sdiff < 0) return -1;
      else return 0;
  } else {
      return diff;
  }
    }

    @Override public String toString() {
  StringBuilder o = new StringBuilder();
  o.append("PriorityMQMessage<");
  if (getBody() != null) o.append(getBody().getClass().getName());
  else o.append("?");
  o.append("> ");
  o.append("( transferAttempts=").append(transferAttempts).append(", ");
  o.append("transfers=").append(transfers).append(", ");
  o.append("logItemIdentifier=").append(logItemIdentifier).append(", ");
  o.append("priority=").append(priority).append(", ");
  o.append("sequence=").append(sequence).append(", ");
  o.append("timestamp=").append(ts).append(" ) ");
  return o.toString();
    }

    public static class Key {

  public Key(long k) {
      this(ByteBuffer.wrap(new byte[8]).putLong(k).array());
  }

  public Key(byte[] k) {
      ByteBuffer buf = ByteBuffer.wrap(k);
      this._priority = new Priority(buf.get());
      long value = 0;
      byte[] b = new byte[6];
      buf.get(b);
      for (int i = 0; i < b.length; i++) {
    value = (value << 8) + (b[i] & 0xff);
      }
      this._timestamp = value;
      this._sequence = new Tiny(buf.get());
  }

  public Key(Priority p, long t, Tiny s) {
      this._priority = p;
      this._timestamp = t;
      this._sequence = s;
  }

  private final Priority _priority;
  private final long _timestamp;
  private final Tiny _sequence;

  public Priority getPriority() { return this._priority; }
  public long getTimestamp() { return this._timestamp; }
  public Tiny getSequence() { return this._sequence; }

  public long getKey() {
      byte[] k = new byte[8];
      ByteBuffer buf = ByteBuffer.wrap(k);
      buf.put(_priority.byteValue());
      for (int i = 0; i < 6; i++) {
    buf.put( (byte)(_timestamp >>> ((6-1-i) * 8)) );
      }
      buf.put(_sequence.byteValue());
      return ByteBuffer.wrap(k).getLong();
  }

  public String toString() {
      StringBuilder o = new StringBuilder();
      o.append("PriorityMQMessage.Key (");
      o.append("priority=").append(_priority).append(", ");
      o.append("timestamp=").append(_timestamp).append(", ");
      o.append("sequence=").append(_sequence).append(")");
      return o.toString();
  }

  public String toCompactString(String prefix) {
      StringBuilder o = new StringBuilder(prefix);
      o.append(_priority).append(':');
      o.append(_timestamp).append(':');
      o.append(_sequence);
      return o.toString();
  }

  public static Key fromCompactString(String s) {
      String[] es = s.split(":");
      if (es.length != 3) throw new IllegalArgumentException("Must be compact string representation of Key.");
      return new Key(new Priority(Integer.parseInt(es[0])),
         Long.parseLong(es[1]),
         new Tiny(Integer.parseInt(es[2])));
  }
    }

}
TOP

Related Classes of com.cloudhopper.mq.message.PriorityMQMessage$Key

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.