001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.broker.region; 018 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.Iterator; 022import java.util.List; 023import java.util.Map; 024import java.util.Set; 025import java.util.concurrent.ConcurrentHashMap; 026import java.util.concurrent.locks.ReentrantReadWriteLock; 027 028import javax.jms.IllegalStateException; 029import javax.jms.JMSException; 030 031import org.apache.activemq.DestinationDoesNotExistException; 032import org.apache.activemq.advisory.AdvisorySupport; 033import org.apache.activemq.broker.ConnectionContext; 034import org.apache.activemq.broker.ConsumerBrokerExchange; 035import org.apache.activemq.broker.ProducerBrokerExchange; 036import org.apache.activemq.broker.region.policy.PolicyEntry; 037import org.apache.activemq.broker.region.virtual.CompositeDestinationFilter; 038import org.apache.activemq.command.ActiveMQDestination; 039import org.apache.activemq.command.ConsumerControl; 040import org.apache.activemq.command.ConsumerId; 041import org.apache.activemq.command.ConsumerInfo; 042import org.apache.activemq.command.Message; 043import org.apache.activemq.command.MessageAck; 044import org.apache.activemq.command.MessageDispatchNotification; 045import org.apache.activemq.command.MessagePull; 046import org.apache.activemq.command.ProducerInfo; 047import org.apache.activemq.command.RemoveSubscriptionInfo; 048import org.apache.activemq.command.Response; 049import org.apache.activemq.filter.DestinationFilter; 050import org.apache.activemq.filter.DestinationMap; 051import org.apache.activemq.security.SecurityContext; 052import org.apache.activemq.thread.TaskRunnerFactory; 053import org.apache.activemq.usage.SystemUsage; 054import org.slf4j.Logger; 055import org.slf4j.LoggerFactory; 056 057/** 058 * 059 */ 060public abstract class AbstractRegion implements Region { 061 062 private static final Logger LOG = LoggerFactory.getLogger(AbstractRegion.class); 063 064 protected final Map<ActiveMQDestination, Destination> destinations = new ConcurrentHashMap<ActiveMQDestination, Destination>(); 065 protected final DestinationMap destinationMap = new DestinationMap(); 066 protected final Map<ConsumerId, Subscription> subscriptions = new ConcurrentHashMap<ConsumerId, Subscription>(); 067 protected final SystemUsage usageManager; 068 protected final DestinationFactory destinationFactory; 069 protected final DestinationStatistics destinationStatistics; 070 protected final RegionStatistics regionStatistics = new RegionStatistics(); 071 protected final RegionBroker broker; 072 protected boolean autoCreateDestinations = true; 073 protected final TaskRunnerFactory taskRunnerFactory; 074 protected final ReentrantReadWriteLock destinationsLock = new ReentrantReadWriteLock(); 075 protected final Map<ConsumerId, Object> consumerChangeMutexMap = new HashMap<ConsumerId, Object>(); 076 protected boolean started; 077 078 public AbstractRegion(RegionBroker broker, DestinationStatistics destinationStatistics, SystemUsage memoryManager, 079 TaskRunnerFactory taskRunnerFactory, DestinationFactory destinationFactory) { 080 if (broker == null) { 081 throw new IllegalArgumentException("null broker"); 082 } 083 this.broker = broker; 084 this.destinationStatistics = destinationStatistics; 085 this.usageManager = memoryManager; 086 this.taskRunnerFactory = taskRunnerFactory; 087 if (destinationFactory == null) { 088 throw new IllegalArgumentException("null destinationFactory"); 089 } 090 this.destinationFactory = destinationFactory; 091 } 092 093 @Override 094 public final void start() throws Exception { 095 started = true; 096 097 Set<ActiveMQDestination> inactiveDests = getInactiveDestinations(); 098 for (Iterator<ActiveMQDestination> iter = inactiveDests.iterator(); iter.hasNext();) { 099 ActiveMQDestination dest = iter.next(); 100 101 ConnectionContext context = new ConnectionContext(); 102 context.setBroker(broker.getBrokerService().getBroker()); 103 context.setSecurityContext(SecurityContext.BROKER_SECURITY_CONTEXT); 104 context.getBroker().addDestination(context, dest, false); 105 } 106 destinationsLock.readLock().lock(); 107 try{ 108 for (Iterator<Destination> i = destinations.values().iterator(); i.hasNext();) { 109 Destination dest = i.next(); 110 dest.start(); 111 } 112 } finally { 113 destinationsLock.readLock().unlock(); 114 } 115 } 116 117 @Override 118 public void stop() throws Exception { 119 started = false; 120 destinationsLock.readLock().lock(); 121 try{ 122 for (Iterator<Destination> i = destinations.values().iterator(); i.hasNext();) { 123 Destination dest = i.next(); 124 dest.stop(); 125 } 126 } finally { 127 destinationsLock.readLock().unlock(); 128 } 129 130 destinationsLock.writeLock().lock(); 131 try { 132 destinations.clear(); 133 regionStatistics.getAdvisoryDestinations().reset(); 134 regionStatistics.getDestinations().reset(); 135 regionStatistics.getAllDestinations().reset(); 136 } finally { 137 destinationsLock.writeLock().unlock(); 138 } 139 } 140 141 @Override 142 public Destination addDestination(ConnectionContext context, ActiveMQDestination destination, 143 boolean createIfTemporary) throws Exception { 144 145 destinationsLock.writeLock().lock(); 146 try { 147 Destination dest = destinations.get(destination); 148 if (dest == null) { 149 if (destination.isTemporary() == false || createIfTemporary) { 150 // Limit the number of destinations that can be created if 151 // maxDestinations has been set on a policy 152 validateMaxDestinations(destination); 153 154 LOG.debug("{} adding destination: {}", broker.getBrokerName(), destination); 155 dest = createDestination(context, destination); 156 // intercept if there is a valid interceptor defined 157 DestinationInterceptor destinationInterceptor = broker.getDestinationInterceptor(); 158 if (destinationInterceptor != null) { 159 dest = destinationInterceptor.intercept(dest); 160 } 161 dest.start(); 162 addSubscriptionsForDestination(context, dest); 163 destinations.put(destination, dest); 164 updateRegionDestCounts(destination, 1); 165 destinationMap.unsynchronizedPut(destination, dest); 166 } 167 if (dest == null) { 168 throw new DestinationDoesNotExistException(destination.getQualifiedName()); 169 } 170 } 171 return dest; 172 } finally { 173 destinationsLock.writeLock().unlock(); 174 } 175 } 176 177 public Map<ConsumerId, Subscription> getSubscriptions() { 178 return subscriptions; 179 } 180 181 182 /** 183 * Updates the counts in RegionStatistics based on whether or not the destination 184 * is an Advisory Destination or not 185 * 186 * @param destination the destination being used to determine which counters to update 187 * @param count the count to add to the counters 188 */ 189 protected void updateRegionDestCounts(ActiveMQDestination destination, int count) { 190 if (destination != null) { 191 if (AdvisorySupport.isAdvisoryTopic(destination)) { 192 regionStatistics.getAdvisoryDestinations().add(count); 193 } else { 194 regionStatistics.getDestinations().add(count); 195 } 196 regionStatistics.getAllDestinations().add(count); 197 } 198 } 199 200 /** 201 * This method checks whether or not the destination can be created based on 202 * {@link PolicyEntry#getMaxDestinations}, if it has been set. Advisory 203 * topics are ignored. 204 * 205 * @param destination 206 * @throws Exception 207 */ 208 protected void validateMaxDestinations(ActiveMQDestination destination) 209 throws Exception { 210 if (broker.getDestinationPolicy() != null) { 211 PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination); 212 // Make sure the destination is not an advisory topic 213 if (entry != null && entry.getMaxDestinations() >= 0 214 && !AdvisorySupport.isAdvisoryTopic(destination)) { 215 // If there is an entry for this destination, look up the set of 216 // destinations associated with this policy 217 // If a destination isn't specified, then just count up 218 // non-advisory destinations (ie count all destinations) 219 int destinationSize = (int) (entry.getDestination() != null ? 220 destinationMap.unsynchronizedGet(entry.getDestination()).size() : regionStatistics.getDestinations().getCount()); 221 if (destinationSize >= entry.getMaxDestinations()) { 222 if (entry.getDestination() != null) { 223 throw new IllegalStateException( 224 "The maxmimum number of destinations allowed ("+ entry.getMaxDestinations() + 225 ") for the policy " + entry.getDestination() + " has already been reached."); 226 // No destination has been set (default policy) 227 } else { 228 throw new IllegalStateException("The maxmimum number of destinations allowed (" 229 + entry.getMaxDestinations() + ") has already been reached."); 230 } 231 } 232 } 233 } 234 } 235 236 protected List<Subscription> addSubscriptionsForDestination(ConnectionContext context, Destination dest) throws Exception { 237 List<Subscription> rc = new ArrayList<Subscription>(); 238 // Add all consumers that are interested in the destination. 239 for (Iterator<Subscription> iter = subscriptions.values().iterator(); iter.hasNext();) { 240 Subscription sub = iter.next(); 241 if (sub.matches(dest.getActiveMQDestination())) { 242 try { 243 ConnectionContext originalContext = sub.getContext() != null ? sub.getContext() : context; 244 dest.addSubscription(originalContext, sub); 245 rc.add(sub); 246 } catch (SecurityException e) { 247 if (sub.isWildcard()) { 248 LOG.debug("Subscription denied for " + sub + " to destination " + 249 dest.getActiveMQDestination() + ": " + e.getMessage()); 250 } else { 251 throw e; 252 } 253 } 254 } 255 } 256 return rc; 257 258 } 259 260 @Override 261 public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) 262 throws Exception { 263 264 // No timeout.. then try to shut down right way, fails if there are 265 // current subscribers. 266 if (timeout == 0) { 267 for (Iterator<Subscription> iter = subscriptions.values().iterator(); iter.hasNext();) { 268 Subscription sub = iter.next(); 269 if (sub.matches(destination) ) { 270 throw new JMSException("Destination still has an active subscription: " + destination); 271 } 272 } 273 } 274 275 if (timeout > 0) { 276 // TODO: implement a way to notify the subscribers that we want to 277 // take the down 278 // the destination and that they should un-subscribe.. Then wait up 279 // to timeout time before 280 // dropping the subscription. 281 } 282 283 LOG.debug("{} removing destination: {}", broker.getBrokerName(), destination); 284 285 destinationsLock.writeLock().lock(); 286 try { 287 Destination dest = destinations.remove(destination); 288 if (dest != null) { 289 updateRegionDestCounts(destination, -1); 290 291 // timeout<0 or we timed out, we now force any remaining 292 // subscriptions to un-subscribe. 293 for (Iterator<Subscription> iter = subscriptions.values().iterator(); iter.hasNext();) { 294 Subscription sub = iter.next(); 295 if (sub.matches(destination)) { 296 dest.removeSubscription(context, sub, 0l); 297 } 298 } 299 destinationMap.unsynchronizedRemove(destination, dest); 300 if (dest instanceof Queue){ 301 ((Queue) dest).purge(); 302 } 303 dispose(context, dest); 304 DestinationInterceptor destinationInterceptor = broker.getDestinationInterceptor(); 305 if (destinationInterceptor != null) { 306 destinationInterceptor.remove(dest); 307 } 308 309 } else { 310 LOG.debug("Cannot remove a destination that doesn't exist: {}", destination); 311 } 312 } finally { 313 destinationsLock.writeLock().unlock(); 314 } 315 } 316 317 /** 318 * Provide an exact or wildcard lookup of destinations in the region 319 * 320 * @return a set of matching destination objects. 321 */ 322 @Override 323 @SuppressWarnings("unchecked") 324 public Set<Destination> getDestinations(ActiveMQDestination destination) { 325 destinationsLock.readLock().lock(); 326 try{ 327 return destinationMap.unsynchronizedGet(destination); 328 } finally { 329 destinationsLock.readLock().unlock(); 330 } 331 } 332 333 @Override 334 public Map<ActiveMQDestination, Destination> getDestinationMap() { 335 return destinations; 336 } 337 338 @Override 339 @SuppressWarnings("unchecked") 340 public Subscription addConsumer(ConnectionContext context, ConsumerInfo info) throws Exception { 341 LOG.debug("{} adding consumer: {} for destination: {}", new Object[]{ broker.getBrokerName(), info.getConsumerId(), info.getDestination() }); 342 ActiveMQDestination destination = info.getDestination(); 343 if (destination != null && !destination.isPattern() && !destination.isComposite()) { 344 // lets auto-create the destination 345 lookup(context, destination,true); 346 } 347 348 Object addGuard; 349 synchronized (consumerChangeMutexMap) { 350 addGuard = consumerChangeMutexMap.get(info.getConsumerId()); 351 if (addGuard == null) { 352 addGuard = new Object(); 353 consumerChangeMutexMap.put(info.getConsumerId(), addGuard); 354 } 355 } 356 synchronized (addGuard) { 357 Subscription o = subscriptions.get(info.getConsumerId()); 358 if (o != null) { 359 LOG.warn("A duplicate subscription was detected. Clients may be misbehaving. Later warnings you may see about subscription removal are a consequence of this."); 360 return o; 361 } 362 363 // We may need to add some destinations that are in persistent store 364 // but not active 365 // in the broker. 366 // 367 // TODO: think about this a little more. This is good cause 368 // destinations are not loaded into 369 // memory until a client needs to use the queue, but a management 370 // agent viewing the 371 // broker will not see a destination that exists in persistent 372 // store. We may want to 373 // eagerly load all destinations into the broker but have an 374 // inactive state for the 375 // destination which has reduced memory usage. 376 // 377 DestinationFilter.parseFilter(info.getDestination()); 378 379 Subscription sub = createSubscription(context, info); 380 381 // At this point we're done directly manipulating subscriptions, 382 // but we need to retain the synchronized block here. Consider 383 // otherwise what would happen if at this point a second 384 // thread added, then removed, as would be allowed with 385 // no mutex held. Remove is only essentially run once 386 // so everything after this point would be leaked. 387 388 // Add the subscription to all the matching queues. 389 // But copy the matches first - to prevent deadlocks 390 List<Destination> addList = new ArrayList<Destination>(); 391 destinationsLock.readLock().lock(); 392 try { 393 for (Destination dest : (Set<Destination>) destinationMap.unsynchronizedGet(info.getDestination())) { 394 addList.add(dest); 395 } 396 // ensure sub visible to any new dest addSubscriptionsForDestination 397 subscriptions.put(info.getConsumerId(), sub); 398 } finally { 399 destinationsLock.readLock().unlock(); 400 } 401 402 List<Destination> removeList = new ArrayList<Destination>(); 403 for (Destination dest : addList) { 404 try { 405 dest.addSubscription(context, sub); 406 removeList.add(dest); 407 } catch (SecurityException e){ 408 if (sub.isWildcard()) { 409 LOG.debug("Subscription denied for " + sub + " to destination " + 410 dest.getActiveMQDestination() + ": " + e.getMessage()); 411 } else { 412 // remove partial subscriptions 413 for (Destination remove : removeList) { 414 try { 415 remove.removeSubscription(context, sub, info.getLastDeliveredSequenceId()); 416 } catch (Exception ex) { 417 LOG.error("Error unsubscribing " + sub + " from " + remove + ": " + ex.getMessage(), ex); 418 } 419 } 420 subscriptions.remove(info.getConsumerId()); 421 removeList.clear(); 422 throw e; 423 } 424 } 425 } 426 removeList.clear(); 427 428 if (info.isBrowser()) { 429 ((QueueBrowserSubscription) sub).destinationsAdded(); 430 } 431 432 return sub; 433 } 434 } 435 436 /** 437 * Get all the Destinations that are in storage 438 * 439 * @return Set of all stored destinations 440 */ 441 @SuppressWarnings("rawtypes") 442 public Set getDurableDestinations() { 443 return destinationFactory.getDestinations(); 444 } 445 446 /** 447 * @return all Destinations that don't have active consumers 448 */ 449 protected Set<ActiveMQDestination> getInactiveDestinations() { 450 Set<ActiveMQDestination> inactiveDests = destinationFactory.getDestinations(); 451 destinationsLock.readLock().lock(); 452 try { 453 inactiveDests.removeAll(destinations.keySet()); 454 } finally { 455 destinationsLock.readLock().unlock(); 456 } 457 return inactiveDests; 458 } 459 460 @Override 461 @SuppressWarnings("unchecked") 462 public void removeConsumer(ConnectionContext context, ConsumerInfo info) throws Exception { 463 LOG.debug("{} removing consumer: {} for destination: {}", new Object[]{ broker.getBrokerName(), info.getConsumerId(), info.getDestination() }); 464 465 Subscription sub = subscriptions.remove(info.getConsumerId()); 466 // The sub could be removed elsewhere - see ConnectionSplitBroker 467 if (sub != null) { 468 469 // remove the subscription from all the matching queues. 470 List<Destination> removeList = new ArrayList<Destination>(); 471 destinationsLock.readLock().lock(); 472 try { 473 for (Destination dest : (Set<Destination>) destinationMap.unsynchronizedGet(info.getDestination())) { 474 removeList.add(dest); 475 } 476 } finally { 477 destinationsLock.readLock().unlock(); 478 } 479 for (Destination dest : removeList) { 480 dest.removeSubscription(context, sub, info.getLastDeliveredSequenceId()); 481 } 482 483 destroySubscription(sub); 484 } 485 synchronized (consumerChangeMutexMap) { 486 consumerChangeMutexMap.remove(info.getConsumerId()); 487 } 488 } 489 490 protected void destroySubscription(Subscription sub) { 491 sub.destroy(); 492 } 493 494 @Override 495 public void removeSubscription(ConnectionContext context, RemoveSubscriptionInfo info) throws Exception { 496 throw new JMSException("Invalid operation."); 497 } 498 499 @Override 500 public void send(final ProducerBrokerExchange producerExchange, Message messageSend) throws Exception { 501 final ConnectionContext context = producerExchange.getConnectionContext(); 502 503 if (producerExchange.isMutable() || producerExchange.getRegionDestination() == null) { 504 final Destination regionDestination = lookup(context, messageSend.getDestination(),false); 505 producerExchange.setRegionDestination(regionDestination); 506 } 507 508 producerExchange.getRegionDestination().send(producerExchange, messageSend); 509 510 if (producerExchange.getProducerState() != null && producerExchange.getProducerState().getInfo() != null){ 511 producerExchange.getProducerState().getInfo().incrementSentCount(); 512 } 513 } 514 515 @Override 516 public void acknowledge(ConsumerBrokerExchange consumerExchange, MessageAck ack) throws Exception { 517 Subscription sub = consumerExchange.getSubscription(); 518 if (sub == null) { 519 sub = subscriptions.get(ack.getConsumerId()); 520 if (sub == null) { 521 if (!consumerExchange.getConnectionContext().isInRecoveryMode()) { 522 LOG.warn("Ack for non existent subscription, ack: {}", ack); 523 throw new IllegalArgumentException("The subscription does not exist: " + ack.getConsumerId()); 524 } else { 525 LOG.debug("Ack for non existent subscription in recovery, ack: {}", ack); 526 return; 527 } 528 } 529 consumerExchange.setSubscription(sub); 530 } 531 sub.acknowledge(consumerExchange.getConnectionContext(), ack); 532 } 533 534 @Override 535 public Response messagePull(ConnectionContext context, MessagePull pull) throws Exception { 536 Subscription sub = subscriptions.get(pull.getConsumerId()); 537 if (sub == null) { 538 throw new IllegalArgumentException("The subscription does not exist: " + pull.getConsumerId()); 539 } 540 return sub.pullMessage(context, pull); 541 } 542 543 protected Destination lookup(ConnectionContext context, ActiveMQDestination destination,boolean createTemporary) throws Exception { 544 Destination dest = null; 545 546 destinationsLock.readLock().lock(); 547 try { 548 dest = destinations.get(destination); 549 } finally { 550 destinationsLock.readLock().unlock(); 551 } 552 553 if (dest == null) { 554 if (isAutoCreateDestinations()) { 555 // Try to auto create the destination... re-invoke broker 556 // from the 557 // top so that the proper security checks are performed. 558 dest = context.getBroker().addDestination(context, destination, createTemporary); 559 } 560 561 if (dest == null) { 562 throw new JMSException("The destination " + destination + " does not exist."); 563 } 564 } 565 return dest; 566 } 567 568 @Override 569 public void processDispatchNotification(MessageDispatchNotification messageDispatchNotification) throws Exception { 570 Subscription sub = subscriptions.get(messageDispatchNotification.getConsumerId()); 571 if (sub != null) { 572 sub.processMessageDispatchNotification(messageDispatchNotification); 573 } else { 574 throw new JMSException("Slave broker out of sync with master - Subscription: " 575 + messageDispatchNotification.getConsumerId() + " on " 576 + messageDispatchNotification.getDestination() + " does not exist for dispatch of message: " 577 + messageDispatchNotification.getMessageId()); 578 } 579 } 580 581 /* 582 * For a Queue/TempQueue, dispatch order is imperative to match acks, so the 583 * dispatch is deferred till the notification to ensure that the 584 * subscription chosen by the master is used. AMQ-2102 585 */ 586 protected void processDispatchNotificationViaDestination(MessageDispatchNotification messageDispatchNotification) 587 throws Exception { 588 Destination dest = null; 589 destinationsLock.readLock().lock(); 590 try { 591 dest = destinations.get(messageDispatchNotification.getDestination()); 592 } finally { 593 destinationsLock.readLock().unlock(); 594 } 595 596 if (dest != null) { 597 dest.processDispatchNotification(messageDispatchNotification); 598 } else { 599 throw new JMSException("Slave broker out of sync with master - Destination: " 600 + messageDispatchNotification.getDestination() + " does not exist for consumer " 601 + messageDispatchNotification.getConsumerId() + " with message: " 602 + messageDispatchNotification.getMessageId()); 603 } 604 } 605 606 @Override 607 public void gc() { 608 for (Subscription sub : subscriptions.values()) { 609 sub.gc(); 610 } 611 612 destinationsLock.readLock().lock(); 613 try { 614 for (Destination dest : destinations.values()) { 615 dest.gc(); 616 } 617 } finally { 618 destinationsLock.readLock().unlock(); 619 } 620 } 621 622 protected abstract Subscription createSubscription(ConnectionContext context, ConsumerInfo info) throws Exception; 623 624 protected Destination createDestination(ConnectionContext context, ActiveMQDestination destination) 625 throws Exception { 626 return destinationFactory.createDestination(context, destination, destinationStatistics); 627 } 628 629 public boolean isAutoCreateDestinations() { 630 return autoCreateDestinations; 631 } 632 633 public void setAutoCreateDestinations(boolean autoCreateDestinations) { 634 this.autoCreateDestinations = autoCreateDestinations; 635 } 636 637 @Override 638 @SuppressWarnings("unchecked") 639 public void addProducer(ConnectionContext context, ProducerInfo info) throws Exception { 640 destinationsLock.readLock().lock(); 641 try { 642 for (Destination dest : (Set<Destination>) destinationMap.unsynchronizedGet(info.getDestination())) { 643 dest.addProducer(context, info); 644 } 645 } finally { 646 destinationsLock.readLock().unlock(); 647 } 648 } 649 650 /** 651 * Removes a Producer. 652 * 653 * @param context 654 * the environment the operation is being executed under. 655 * @throws Exception 656 * TODO 657 */ 658 @Override 659 @SuppressWarnings("unchecked") 660 public void removeProducer(ConnectionContext context, ProducerInfo info) throws Exception { 661 destinationsLock.readLock().lock(); 662 try { 663 for (Destination dest : (Set<Destination>) destinationMap.unsynchronizedGet(info.getDestination())) { 664 dest.removeProducer(context, info); 665 } 666 } finally { 667 destinationsLock.readLock().unlock(); 668 } 669 } 670 671 protected void dispose(ConnectionContext context, Destination dest) throws Exception { 672 dest.dispose(context); 673 dest.stop(); 674 destinationFactory.removeDestination(dest); 675 } 676 677 @Override 678 public void processConsumerControl(ConsumerBrokerExchange consumerExchange, ConsumerControl control) { 679 Subscription sub = subscriptions.get(control.getConsumerId()); 680 if (sub != null && sub instanceof AbstractSubscription) { 681 ((AbstractSubscription) sub).setPrefetchSize(control.getPrefetch()); 682 if (broker.getDestinationPolicy() != null) { 683 PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(control.getDestination()); 684 if (entry != null) { 685 entry.configurePrefetch(sub); 686 } 687 } 688 LOG.debug("setting prefetch: {}, on subscription: {}; resulting value: {}", new Object[]{ control.getPrefetch(), control.getConsumerId(), sub.getConsumerInfo().getPrefetchSize()}); 689 try { 690 lookup(consumerExchange.getConnectionContext(), control.getDestination(),false).wakeup(); 691 } catch (Exception e) { 692 LOG.warn("failed to deliver post consumerControl dispatch-wakeup, to destination: {}", control.getDestination(), e); 693 } 694 } 695 } 696 697 @Override 698 public void reapplyInterceptor() { 699 destinationsLock.writeLock().lock(); 700 try { 701 DestinationInterceptor destinationInterceptor = broker.getDestinationInterceptor(); 702 Map<ActiveMQDestination, Destination> map = getDestinationMap(); 703 for (ActiveMQDestination key : map.keySet()) { 704 Destination destination = map.get(key); 705 if (destination instanceof CompositeDestinationFilter) { 706 destination = ((CompositeDestinationFilter) destination).next; 707 } 708 if (destinationInterceptor != null) { 709 destination = destinationInterceptor.intercept(destination); 710 } 711 getDestinationMap().put(key, destination); 712 Destination prev = destinations.put(key, destination); 713 if (prev == null) { 714 updateRegionDestCounts(key, 1); 715 } 716 } 717 } finally { 718 destinationsLock.writeLock().unlock(); 719 } 720 } 721}