Package org.xmlBlaster.engine.queuemsg

Source Code of org.xmlBlaster.engine.queuemsg.MsgQueueUpdateEntry

/*------------------------------------------------------------------------------
Name:      MsgQueueUpdateEntry.java
Project:   xmlBlaster.org
Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
------------------------------------------------------------------------------*/
package org.xmlBlaster.engine.queuemsg;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.xmlBlaster.engine.MsgUnitWrapper;
import org.xmlBlaster.engine.ServerScope;
import org.xmlBlaster.util.SessionName;
import org.xmlBlaster.util.StringPairTokenizer;
import org.xmlBlaster.util.Timestamp;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.def.Constants;
import org.xmlBlaster.util.def.PriorityEnum;
import org.xmlBlaster.util.queue.StorageId;
import org.xmlBlaster.util.queue.jdbc.XBRef;

/**
* Wraps an publish() message into an entry for a sorted queue.
* @author michele@laghi.eu
* @author xmlBlaster@marcelruff.info
*/
public final class MsgQueueUpdateEntry extends ReferenceEntry
{
   private static Logger log = Logger.getLogger(MsgQueueUpdateEntry.class.getName());
   private static final long serialVersionUID = 1L;
   private final static String ME = "MsgQueueUpdateEntry";
   private final String subscriptionId;
   /** Contains state|updateOneway|forceDestroy, for example "OK|oneway" or "OK" */
   private final String flag;
   private final String state;
   private final boolean updateOneway;

   /**
    * A new message object is fed by method publish().
    * @param msgUnit The raw data, we keep a weak reference only on this data so it can be garbage collected
    */
   public MsgQueueUpdateEntry(ServerScope glob, MsgUnitWrapper msgUnitWrapper, StorageId storageId, SessionName receiver,
                              String subscriptionId, boolean wantUpdateOneway) throws XmlBlasterException {
      this(glob, msgUnitWrapper, (Timestamp)null, storageId, receiver, subscriptionId, wantUpdateOneway);                          
   }  
  
   /**
    * convenience constructor to allow passing an already given uniqueId (the timestamp)
    * @param glob
    * @param msgUnitWrapper
    * @param timestamp
    * @param storageId
    * @param receiver
    * @param subscriptionId
    * @param wantUpdateOneway
    * @throws XmlBlasterException
    */
   public MsgQueueUpdateEntry(ServerScope glob, MsgUnitWrapper msgUnitWrapper, Timestamp timestamp, StorageId storageId, SessionName receiver,
                              String subscriptionId, boolean wantUpdateOneway) throws XmlBlasterException {
      super(ME, glob, ServerEntryFactory.ENTRY_TYPE_UPDATE_REF, msgUnitWrapper, timestamp, storageId, receiver);
      this.getMsgQosData().setSender(msgUnitWrapper.getMsgQosData().getSender());
      this.subscriptionId = subscriptionId;
      this.state = msgUnitWrapper.getMsgUnit().getQosData().getState();
      this.updateOneway = wantUpdateOneway;
      String flagTmp = (this.updateOneway) ? this.state+"|oneway" : this.state;
      if (msgUnitWrapper.getMsgQosData().getForceDestroyProp().getValue() == true)
         flagTmp += "|forceDestroy";
      this.flag = flagTmp;
      if (log.isLoggable(Level.FINE)) log.fine("Created new MsgQueueUpdateEntry for published message '" + msgUnitWrapper.getLogId() + "', id=" + getUniqueId() + " prio=" + priority.toString());
   }

   /**
    * For persistence recovery
    * The params qos, key, content can be null (the unparsed raw message)
    */
   public MsgQueueUpdateEntry(ServerScope glob, PriorityEnum priority, StorageId storageId, Timestamp updateEntryTimestamp,
                              String keyOid, long msgUnitWrapperUniqueId, boolean persistent, long sizeInBytes,
                              SessionName receiver, String subscriptionId, String flag,
                              int redeliverCount,
                              String qos, String key, byte[] content) throws XmlBlasterException {
      super(ME, glob, ServerEntryFactory.ENTRY_TYPE_UPDATE_REF, priority, storageId,
            updateEntryTimestamp, keyOid, msgUnitWrapperUniqueId, persistent, receiver,
            qos, key, content);
      this.subscriptionId = subscriptionId;
      this.flag = flag;
      int index = this.flag.indexOf("|");
      this.state = (index == -1) ? this.flag : this.flag.substring(0,index);
      this.updateOneway = (index != -1 && this.flag.indexOf("|oneway") != -1) ? true : false;
      super.redeliverCounter = redeliverCount;
      if (sizeInBytes != getSizeInBytes()) {
         log.severe("Internal problem: From persistence sizeInBytes=" + sizeInBytes + " but expected " + getSizeInBytes());
      }
   }
  
   protected boolean isForceDestroy() {
      return this.flag.indexOf("forceDestroy") != -1;
   }

   /**
    * Copy constructor, used to get a shallow clone, we still reference the original MsgUnitWrapper.
    */
   public MsgQueueUpdateEntry(MsgQueueUpdateEntry entry, StorageId storageId) throws XmlBlasterException {
      this(entry.getGlobal(), entry.getMsgUnitWrapper(), entry.uniqueIdTimestamp, storageId,
           entry.getReceiver(), entry.getSubscriptionId(), entry.updateOneway());
   }

   public String getSubscriptionId() {
      return this.subscriptionId;
   }

   public String getState() {
      return this.state;
   }

   /**
    * Holds state and updateOneway information
    * @return for example "OK|oneway"
    */
   public String getFlag() {
      return this.flag;
   }

   /**
    * true if the subscriber has passed <updateOneway> in his SubscribeQos
    */
   public boolean updateOneway() {
      return this.updateOneway;
   }

   public long getSizeInBytes() {
      return 179; // This is a guess only, we have only a reference on the real data
                  // The bytes consumed are a 'new Timestamp' and a 'new MsgQueueUpdateEntry'
      // IBM JDK 1.3.1 approx 172 bytes/entry
      // SUN JDK 1.4.1 approx 179 bytes/entry
   }

   /**
    * The embedded object for this implementing class is an Object[6] for transient
    * messages and Object[9] for persistent messages.
    * <p>
    * We need to store the 'meat' for persistent messages as well
    * After a recovery the 'meat's reference counter is not valid so
    * we need to have all informations duplicated in each callback queue.
    * </p>
    */
   public Object getEmbeddedObject() {
      if (ReferenceEntry.STRICT_REFERENCE_COUNTING) {
            Object[] obj = {
                          this.keyOid,
                          new Long(this.msgUnitWrapperUniqueId),
                          this.receiver.getAbsoluteName(),
                          this.subscriptionId,
                          this.flag,
                          new Integer(getRedeliverCounter())
                           };
            return obj;
      }
      else {
         MsgUnitWrapper w = null;
         if (isPersistent() && ((w = getMsgUnitWrapper()) != null)) {
            Object[] meat = (Object[])w.getEmbeddedObject();
            Object[] obj = {
                             this.keyOid,
                             new Long(this.msgUnitWrapperUniqueId),
                             this.receiver.getAbsoluteName(),
                             this.subscriptionId,
                             this.flag,
                             new Integer(getRedeliverCounter()),
                             meat[0],   // QoS
                             meat[1],   // key
                             meat[2]    // content
                              };
            return obj;
         }
         else {
            Object[] obj = {
                          this.keyOid,
                          new Long(this.msgUnitWrapperUniqueId),
                          this.receiver.getAbsoluteName(),
                          this.subscriptionId,
                          this.flag,
                          new Integer(getRedeliverCounter())
                           };
            return obj;
         }
      }
   }

   /**
    * Returns a shallow clone
    */
   public Object clone() {
      MsgQueueUpdateEntry entry = null;
      entry = (MsgQueueUpdateEntry)super.clone();
      return entry;
   }

   /**
    * Dump state of this object into XML.
    */
   public final String toXml() {
      return toXml((String)null);
   }

   /**
    * Dump state of this object into XML.
    * @param extraOffset indenting of tags
    */
   public final String toXml(String extraOffset) {
      StringBuffer sb = new StringBuffer(1000);
      if (extraOffset == null) extraOffset = "";
      String offset = Constants.OFFSET + extraOffset;
     
      boolean forceReadable = true;

      Timestamp ts = new Timestamp(msgUnitWrapperUniqueId);

      sb.append(offset).append("<MsgQueueUpdateEntry");
      sb.append(" id='").append(uniqueIdTimestamp.getTimestamp()).append("'");
      sb.append(" storageId='").append(getStorageId()).append("'");
      sb.append(offset).append(" keyOid='").append(getKeyOid()).append("'");
      sb.append(" msgUnitRcvTimestamp='").append(msgUnitWrapperUniqueId).append("'");
      sb.append(" msgUnitRcvTimestampStr='").append(ts.toString()).append("'");
      sb.append(offset).append(" sender='").append(getSender()).append("'");
      sb.append(" receiver='").append(getReceiver().getAbsoluteName()).append("'");
      sb.append(offset).append(" persistent='").append(isPersistent()).append("'");
      sb.append(" subscriptionId='").append(getSubscriptionId()).append("'");
      sb.append(" redeliverCounter='").append(getRedeliverCounter()).append("'");
      sb.append(offset).append(" isExpired='").append(isExpired()).append("'");
      sb.append(" isDestroyed='").append(isDestroyed()).append("'");
      sb.append(" flag='").append(getFlag()).append("'");
      {
         MsgUnitWrapper msgUnitWrapper = getMsgUnitWrapper();
            if (msgUnitWrapper != null)
               sb.append(offset).append(msgUnitWrapper.toXml(extraOffset+Constants.INDENT, forceReadable));
      }
      sb.append("/>");
      return sb.toString();
   }

   public XBRef getRef() {
      XBRef ref = super.getRef();
      Map map = new HashMap/*<String, String>*/();
      map.put(XBRef.KEY_OID, keyOid);
      map.put(XBRef.MSG_WRAPPER_ID, "" + msgUnitWrapperUniqueId);
      map.put(XBRef.RECEIVER_STR, receiver.getAbsoluteName());
      map.put(XBRef.SUB_ID, subscriptionId);
      map.put(XBRef.FLAG, flag);
      map.put(XBRef.REDELIVER_COUNTER, "" + redeliverCounter);
      ref.setMetaInfo(StringPairTokenizer.mapToCSV(map));
      ref.setMeatId(msgUnitWrapperUniqueId);
      return ref;
   }
  
}
TOP

Related Classes of org.xmlBlaster.engine.queuemsg.MsgQueueUpdateEntry

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.