/* */ package org.jboss.messaging.core.impl;
/* */
/* */ import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
/* */ import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
/* */ import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt;
/* */ import java.util.ArrayList;
/* */ import java.util.Collection;
/* */ import java.util.Collections;
/* */ import java.util.HashSet;
/* */ import java.util.Iterator;
/* */ import java.util.LinkedHashMap;
/* */ import java.util.LinkedList;
/* */ import java.util.List;
/* */ import java.util.Map;
/* */ import java.util.Set;
/* */ import org.jboss.jms.server.MessagingTimeoutFactory;
/* */ import org.jboss.logging.Logger;
/* */ import org.jboss.messaging.core.contract.Delivery;
/* */ import org.jboss.messaging.core.contract.DeliveryObserver;
/* */ import org.jboss.messaging.core.contract.Distributor;
/* */ import org.jboss.messaging.core.contract.Filter;
/* */ import org.jboss.messaging.core.contract.Message;
/* */ import org.jboss.messaging.core.contract.MessageReference;
/* */ import org.jboss.messaging.core.contract.MessageStore;
/* */ import org.jboss.messaging.core.contract.PersistenceManager;
/* */ import org.jboss.messaging.core.contract.PersistenceManager.InitialLoadInfo;
/* */ import org.jboss.messaging.core.contract.Queue;
/* */ import org.jboss.messaging.core.contract.Receiver;
/* */ import org.jboss.messaging.core.impl.clusterconnection.MessageSucker;
/* */ import org.jboss.messaging.core.impl.tx.Transaction;
/* */ import org.jboss.messaging.util.prioritylinkedlist.PriorityLinkedList;
/* */ import org.jboss.util.timeout.Timeout;
/* */ import org.jboss.util.timeout.TimeoutFactory;
/* */ import org.jboss.util.timeout.TimeoutTarget;
/* */
/* */ public class MessagingQueue extends PagingChannelSupport
/* */ implements Queue
/* */ {
/* 73 */ private static final Logger log = Logger.getLogger(MessagingQueue.class);
/* */ private static final long DEFAULT_RECOVER_DELIVERIES_TIMEOUT = 3000000L;
/* */ private int nodeID;
/* */ protected String name;
/* */ protected Filter filter;
/* */ protected boolean clustered;
/* */ protected Distributor remoteDistributor;
/* */ protected Distributor localDistributor;
/* 91 */ private boolean trace = log.isTraceEnabled();
/* */ private Set suckers;
/* */ private boolean handleFlowControlForConsumers;
/* */ private Map recoveryArea;
/* */ private Map recoveryMap;
/* */ private long recoverDeliveriesTimeout;
/* */
/* */ public MessagingQueue(int nodeID, String name, long id, MessageStore ms, PersistenceManager pm, boolean recoverable, int maxSize, Filter filter, int fullSize, int pageSize, int downCacheSize, boolean clustered, long recoverDeliveriesTimeout)
/* */ {
/* 110 */ super(id, ms, pm, recoverable, maxSize, fullSize, pageSize, downCacheSize);
/* */
/* 112 */ setup(nodeID, name, filter, clustered, recoverDeliveriesTimeout);
/* */ }
/* */
/* */ public MessagingQueue(int nodeID, String name, long id, MessageStore ms, PersistenceManager pm, boolean recoverable, Filter filter, boolean clustered)
/* */ {
/* 122 */ super(id, ms, pm, recoverable, -1, 100000, 2000, 2000);
/* */
/* 124 */ setup(nodeID, name, filter, clustered, 3000000L);
/* */ }
/* */
/* */ public MessagingQueue(int nodeID, String name, long id, MessageStore ms, PersistenceManager pm, boolean recoverable, int maxSize, Filter filter, boolean clustered)
/* */ {
/* 131 */ super(id, ms, pm, recoverable, maxSize);
/* */
/* 133 */ setup(nodeID, name, filter, clustered, 3000000L);
/* */ }
/* */
/* */ public MessagingQueue(int nodeID, String name, long id, boolean recoverable, Filter filter, boolean clustered)
/* */ {
/* 140 */ super(id, null, null, recoverable, -1);
/* */
/* 142 */ setup(nodeID, name, filter, clustered, 3000000L);
/* */ }
/* */
/* */ private void setup(int nodeID, String name, Filter filter, boolean clustered, long recoverDeliveriesTimeout)
/* */ {
/* 147 */ this.nodeID = nodeID;
/* */
/* 149 */ this.name = name;
/* */
/* 151 */ this.filter = filter;
/* */
/* 153 */ this.clustered = clustered;
/* */
/* 155 */ this.recoverDeliveriesTimeout = recoverDeliveriesTimeout;
/* */
/* 157 */ this.localDistributor = new DistributorWrapper(new RoundRobinDistributor());
/* */
/* 159 */ this.remoteDistributor = new DistributorWrapper(new RoundRobinDistributor());
/* */
/* 161 */ this.distributor = new ClusterRoundRobinDistributor(this.localDistributor, this.remoteDistributor);
/* */
/* 163 */ this.suckers = new HashSet();
/* */
/* 165 */ this.recoveryArea = new ConcurrentReaderHashMap();
/* */
/* 167 */ this.recoveryMap = Collections.synchronizedMap(new LinkedHashMap());
/* */ }
/* */
/* */ public int getNodeID()
/* */ {
/* 175 */ return this.nodeID;
/* */ }
/* */
/* */ public String getName()
/* */ {
/* 180 */ return this.name;
/* */ }
/* */
/* */ public Filter getFilter()
/* */ {
/* 185 */ return this.filter;
/* */ }
/* */
/* */ public boolean isClustered()
/* */ {
/* 190 */ return this.clustered;
/* */ }
/* */
/* */ public Distributor getLocalDistributor()
/* */ {
/* 195 */ return this.localDistributor;
/* */ }
/* */
/* */ public Distributor getRemoteDistributor()
/* */ {
/* 200 */ return this.remoteDistributor;
/* */ }
/* */
/* */ public void mergeIn(long theChannelID, int nodeID)
/* */ throws Exception
/* */ {
/* 210 */ if (this.trace) log.trace("Merging queue " + this.channelID + " node id " + nodeID + " into " + this + " initially refs:" + this.messageRefs.size());
/* */
/* 213 */ synchronized (this.lock)
/* */ {
/* 215 */ flushDownCache();
/* */
/* 217 */ PersistenceManager.InitialLoadInfo ili = this.pm.mergeAndLoad(theChannelID, this.channelID, this.fullSize - this.messageRefs.size(), this.firstPagingOrder, this.nextPagingOrder);
/* */
/* 221 */ if (this.trace) log.trace("Loaded " + ili.getRefInfos().size() + " refs");
/* */
/* 223 */ doLoad(ili);
/* */
/* 225 */ Map toRecover = (Map)this.recoveryArea.remove(new Integer(nodeID));
/* */
/* 227 */ if (this.trace) log.trace("To recover is: " + toRecover);
/* */
/* 229 */ LinkedList toTimeout = new LinkedList();
/* */
/* 231 */ if (toRecover != null)
/* */ {
/* 235 */ if (this.trace) log.trace("Recovery area is not empty, putting refs in recovery map");
/* */
/* 237 */ Iterator iter = this.messageRefs.iterator();
/* */
/* 239 */ while (iter.hasNext())
/* */ {
/* 241 */ MessageReference ref = (MessageReference)iter.next();
/* */
/* 243 */ Message message = ref.getMessage();
/* */
/* 245 */ String sessionID = (String)toRecover.remove(new Long(message.getMessageID()));
/* */
/* 247 */ if (sessionID != null)
/* */ {
/* 249 */ if (this.trace) log.trace("Added ref " + ref + " to recovery map");
/* */
/* 251 */ RecoveryEntry re = new RecoveryEntry();
/* 252 */ re.ref = ref;
/* 253 */ re.sessionID = sessionID;
/* */
/* 255 */ this.recoveryMap.put(new Long(message.getMessageID()), re);
/* */
/* 257 */ this.deliveringCount.increment();
/* */
/* 259 */ iter.remove();
/* */
/* 261 */ toTimeout.addLast(ref);
/* */ }
/* */
/* */ }
/* */
/* 273 */ MessagingTimeoutFactory.instance.getFactory().schedule(System.currentTimeMillis() + this.recoverDeliveriesTimeout, new ClearRecoveryMapTimeoutTarget(toTimeout));
/* */
/* 276 */ if (this.trace) log.trace("Set timeout to fire in " + this.recoverDeliveriesTimeout);
/* */ }
/* */
/* 279 */ deliverInternal();
/* */ }
/* */ }
/* */
/* */ public List recoverDeliveries(List messageIds)
/* */ {
/* 285 */ if (this.trace) log.trace("Recovering deliveries");
/* */
/* 287 */ List refs = new ArrayList();
/* */
/* 289 */ Iterator iter = messageIds.iterator();
/* */
/* 291 */ while (iter.hasNext())
/* */ {
/* 293 */ Long messageID = (Long)iter.next();
/* */
/* 295 */ RecoveryEntry re = (RecoveryEntry)this.recoveryMap.remove(messageID);
/* */
/* 299 */ if (re != null)
/* */ {
/* 301 */ Delivery del = new SimpleDelivery(this, re.ref);
/* */
/* 303 */ if (this.trace) log.trace("Recovered ref " + re.ref);
/* */
/* 305 */ refs.add(del);
/* */ }
/* */ }
/* */
/* 309 */ return refs;
/* */ }
/* */
/* */ public void removeStrandedReferences(String sessionID)
/* */ {
/* 314 */ if (this.trace) log.trace("Removing stranded references for session " + sessionID);
/* */
/* 319 */ Iterator iter = this.recoveryMap.values().iterator();
/* */
/* 321 */ if (this.trace) log.trace("Scanning recovery map for stray entries for session");
/* */
/* 323 */ List toCancel = new ArrayList();
/* */
/* 325 */ while (iter.hasNext())
/* */ {
/* 327 */ RecoveryEntry re = (RecoveryEntry)iter.next();
/* */
/* 329 */ if (this.trace) log.trace("Session id id " + re.sessionID);
/* */
/* 331 */ if (re.sessionID.equals(sessionID))
/* */ {
/* 333 */ MessageReference ref = re.ref;
/* */
/* 335 */ iter.remove();
/* */
/* 339 */ toCancel.add(ref);
/* */ }
/* */ }
/* */
/* 343 */ for (int i = toCancel.size() - 1; i >= 0; i--)
/* */ {
/* 345 */ MessageReference ref = (MessageReference)toCancel.get(i);
/* */
/* 347 */ synchronized (this.lock)
/* */ {
/* 349 */ this.messageRefs.addFirst(ref, ref.getMessage().getPriority());
/* */
/* 352 */ this.deliveringCount.decrement();
/* */ }
/* */
/* 355 */ if (!this.trace) continue; log.trace("Found one, added back on queue");
/* */ }
/* */ }
/* */
/* */ public void registerSucker(MessageSucker sucker)
/* */ {
/* 362 */ if (this.trace) log.trace(this + " Registering sucker " + sucker);
/* */
/* 364 */ synchronized (this.lock)
/* */ {
/* 366 */ if (!this.suckers.contains(sucker))
/* */ {
/* 368 */ this.suckers.add(sucker);
/* */
/* 370 */ this.handleFlowControlForConsumers = true;
/* */
/* 372 */ if ((getReceiversReady()) && (this.localDistributor.getNumberOfReceivers() > 0))
/* */ {
/* 374 */ if (this.trace) log.trace(this + " receivers ready so setting consumer to true");
/* */
/* 376 */ sucker.setConsuming(true);
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */ public boolean unregisterSucker(MessageSucker sucker)
/* */ {
/* 384 */ synchronized (this.lock)
/* */ {
/* 386 */ boolean removed = this.suckers.remove(sucker);
/* */
/* 388 */ if ((removed) && (this.suckers.isEmpty()))
/* */ {
/* 390 */ this.handleFlowControlForConsumers = false;
/* */ }
/* */
/* 393 */ return removed;
/* */ }
/* */ }
/* */
/* */ public int getFullSize()
/* */ {
/* 399 */ return this.fullSize;
/* */ }
/* */
/* */ public int getPageSize()
/* */ {
/* 404 */ return this.pageSize;
/* */ }
/* */
/* */ public int getDownCacheSize()
/* */ {
/* 409 */ return this.downCacheSize;
/* */ }
/* */
/* */ public void addToRecoveryArea(int nodeID, long messageID, String sessionID)
/* */ {
/* 414 */ if (this.trace) log.trace("Adding message id " + messageID + " to recovery area from node " + nodeID);
/* */
/* 420 */ Integer nid = new Integer(nodeID);
/* */
/* 422 */ Map ids = (Map)this.recoveryArea.get(nid);
/* */
/* 424 */ if (ids == null)
/* */ {
/* 426 */ ids = new ConcurrentHashMap();
/* */
/* 428 */ this.recoveryArea.put(nid, ids);
/* */ }
/* */
/* 431 */ ids.put(new Long(messageID), sessionID);
/* */ }
/* */
/* */ public void removeFromRecoveryArea(int nodeID, long messageID)
/* */ {
/* 436 */ if (this.trace) log.trace("Removing message id " + messageID + " to recovery area from node " + nodeID);
/* */
/* 438 */ Integer nid = new Integer(nodeID);
/* */
/* 440 */ Map ids = (Map)this.recoveryArea.get(nid);
/* */
/* 446 */ if ((ids != null) && (ids.remove(new Long(messageID)) != null))
/* */ {
/* 448 */ if (ids.isEmpty())
/* */ {
/* 450 */ this.recoveryArea.remove(nid);
/* */ }
/* */ }
/* */ }
/* */
/* */ public void removeAllFromRecoveryArea(int nodeID)
/* */ {
/* 457 */ if (this.trace) log.trace("Removing all from recovery area for node " + nodeID);
/* */
/* 459 */ boolean removed = this.recoveryArea.remove(new Integer(nodeID)) != null;
/* */
/* 461 */ if (this.trace) log.trace("Removed:" + removed);
/* */ }
/* */
/* */ public void addAllToRecoveryArea(int nodeID, Map ids)
/* */ {
/* 466 */ if (this.trace) log.trace("Adding all from recovery area for node " + nodeID + " set " + ids);
/* */
/* 468 */ Integer nid = new Integer(nodeID);
/* */
/* 470 */ if (!(ids instanceof ConcurrentHashMap))
/* */ {
/* 472 */ ids = new ConcurrentHashMap(ids);
/* */ }
/* */
/* 475 */ if (this.trace) log.trace("Adding " + ids.size() + " ids to recovery area for node " + nodeID);
/* */
/* 477 */ this.recoveryArea.put(nid, ids);
/* */
/* 479 */ if (this.trace) log.trace("Added");
/* */ }
/* */
/* */ public long getRecoverDeliveriesTimeout()
/* */ {
/* 484 */ return this.recoverDeliveriesTimeout;
/* */ }
/* */
/* */ public Map getRecoveryArea()
/* */ {
/* 491 */ if (this.trace) log.trace("Getting recovery area, it is " + this.recoveryArea);
/* */
/* 493 */ return this.recoveryArea;
/* */ }
/* */
/* */ public int getRecoveryMapSize()
/* */ {
/* 498 */ return this.recoveryMap.size();
/* */ }
/* */
/* */ protected void deliverInternal()
/* */ {
/* 505 */ super.deliverInternal();
/* */
/* 507 */ if (this.trace) log.trace(this + " deliverInternal");
/* */
/* 509 */ if ((this.handleFlowControlForConsumers) && (getReceiversReady()) && (this.localDistributor.getNumberOfReceivers() > 0) && (this.messageRefs.isEmpty()))
/* */ {
/* 512 */ if (this.trace) log.trace("Informing suckers");
/* */
/* 515 */ informSuckers(true);
/* */ }
/* */ }
/* */
/* */ protected void setReceiversReady(boolean receiversReady)
/* */ {
/* 521 */ if (this.trace) log.trace(this + " setReceiversReady " + receiversReady);
/* */
/* 523 */ this.receiversReady = receiversReady;
/* */
/* 525 */ if ((this.handleFlowControlForConsumers) && (!receiversReady))
/* */ {
/* 528 */ informSuckers(false);
/* */ }
/* */ }
/* */
/* */ public String toString()
/* */ {
/* 536 */ return "Queue[" + System.identityHashCode(this) + "/" + this.nodeID + "/" + this.channelID + "-" + this.name + "]";
/* */ }
/* */
/* */ public boolean equals(Object other)
/* */ {
/* 541 */ if (!(other instanceof MessagingQueue))
/* */ {
/* 543 */ return false;
/* */ }
/* */
/* 546 */ MessagingQueue queue = (MessagingQueue)other;
/* */
/* 548 */ return (this.nodeID == queue.nodeID) && (this.name.equals(queue.name));
/* */ }
/* */
/* */ private void informSuckers(boolean consume)
/* */ {
/* 559 */ Iterator iter = this.suckers.iterator();
/* */
/* 561 */ while (iter.hasNext())
/* */ {
/* 563 */ MessageSucker sucker = (MessageSucker)iter.next();
/* */
/* 565 */ sucker.setConsuming(consume);
/* */ }
/* */ }
/* */
/* */ private class ClearRecoveryMapTimeoutTarget
/* */ implements TimeoutTarget
/* */ {
/* */ private List ids;
/* */
/* */ ClearRecoveryMapTimeoutTarget(List ids)
/* */ {
/* 674 */ this.ids = ids;
/* */ }
/* */
/* */ public void timedOut(Timeout timeout)
/* */ {
/* 679 */ if (MessagingQueue.this.trace) MessagingQueue.log.trace("ClearRecoveryMap timeout fired");
/* */
/* 681 */ Iterator iter = this.ids.iterator();
/* */
/* 683 */ boolean added = false;
/* */
/* 685 */ while (iter.hasNext())
/* */ {
/* 687 */ MessageReference ref = (MessageReference)iter.next();
/* */
/* 689 */ Object obj = MessagingQueue.this.recoveryMap.remove(new Long(ref.getMessage().getMessageID()));
/* */
/* 691 */ if (obj != null)
/* */ {
/* 693 */ if (MessagingQueue.this.trace) MessagingQueue.log.trace("Adding ref " + ref + " back into queue");
/* */
/* 695 */ synchronized (MessagingQueue.this.lock)
/* */ {
/* 697 */ MessagingQueue.this.messageRefs.addFirst(ref, ref.getMessage().getPriority());
/* */
/* 699 */ MessagingQueue.this.deliveringCount.decrement();
/* */ }
/* */
/* 702 */ added = true;
/* */ }
/* */ }
/* */
/* 706 */ if (added)
/* */ {
/* 708 */ synchronized (MessagingQueue.this.lock)
/* */ {
/* 710 */ MessagingQueue.this.deliverInternal();
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */ static class RecoveryEntry
/* */ {
/* */ String sessionID;
/* */ MessageReference ref;
/* */ }
/* */
/* */ protected class DistributorWrapper
/* */ implements Distributor
/* */ {
/* */ private Distributor distributor;
/* */
/* */ protected DistributorWrapper(Distributor distributor)
/* */ {
/* 577 */ this.distributor = distributor;
/* */ }
/* */
/* */ public Delivery handle(DeliveryObserver observer, MessageReference reference, Transaction tx)
/* */ {
/* 582 */ return this.distributor.handle(observer, reference, tx);
/* */ }
/* */
/* */ public boolean add(Receiver receiver)
/* */ {
/* 587 */ if (MessagingQueue.this.trace) MessagingQueue.log.trace(this + " attempting to add receiver " + receiver);
/* */
/* 589 */ synchronized (MessagingQueue.this.lock)
/* */ {
/* 591 */ boolean added = this.distributor.add(receiver);
/* */
/* 593 */ if (MessagingQueue.this.trace) MessagingQueue.log.trace("receiver " + receiver + (added ? "" : " NOT") + " added");
/* */
/* 595 */ MessagingQueue.this.setReceiversReady(true);
/* */
/* 597 */ return added;
/* */ }
/* */ }
/* */
/* */ public void clear()
/* */ {
/* 603 */ synchronized (MessagingQueue.this.lock)
/* */ {
/* 605 */ this.distributor.clear();
/* */ }
/* */ }
/* */
/* */ public boolean contains(Receiver receiver)
/* */ {
/* 611 */ synchronized (MessagingQueue.this.lock)
/* */ {
/* 613 */ return this.distributor.contains(receiver);
/* */ }
/* */ }
/* */
/* */ public int getNumberOfReceivers()
/* */ {
/* 619 */ synchronized (MessagingQueue.this.lock)
/* */ {
/* 621 */ return this.distributor.getNumberOfReceivers();
/* */ }
/* */ }
/* */
/* */ public Iterator iterator()
/* */ {
/* 627 */ synchronized (MessagingQueue.this.lock)
/* */ {
/* 629 */ return this.distributor.iterator();
/* */ }
/* */ }
/* */
/* */ public boolean remove(Receiver receiver)
/* */ {
/* 635 */ synchronized (MessagingQueue.this.lock)
/* */ {
/* 637 */ boolean removed = this.distributor.remove(receiver);
/* */
/* 639 */ if (removed)
/* */ {
/* 641 */ if (MessagingQueue.this.localDistributor.getNumberOfReceivers() == 0)
/* */ {
/* 644 */ MessagingQueue.this.informSuckers(false);
/* */
/* 646 */ if (MessagingQueue.this.remoteDistributor.getNumberOfReceivers() == 0)
/* */ {
/* 648 */ MessagingQueue.this.setReceiversReady(false);
/* */ }
/* */ }
/* */ }
/* */
/* 653 */ if (MessagingQueue.this.trace) MessagingQueue.log.trace(this + (removed ? " removed " : " did NOT remove ") + receiver);
/* */
/* 655 */ return removed;
/* */ }
/* */ }
/* */ }
/* */ }
/* Location: /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name: org.jboss.messaging.core.impl.MessagingQueue
* JD-Core Version: 0.6.0
*/