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.advisory.AdvisorySupport; 032import org.apache.activemq.broker.ConnectionContext; 033import org.apache.activemq.broker.ConsumerBrokerExchange; 034import org.apache.activemq.broker.ProducerBrokerExchange; 035import org.apache.activemq.broker.region.policy.PolicyEntry; 036import org.apache.activemq.broker.region.virtual.CompositeDestinationFilter; 037import org.apache.activemq.command.ActiveMQDestination; 038import org.apache.activemq.command.ConsumerControl; 039import org.apache.activemq.command.ConsumerId; 040import org.apache.activemq.command.ConsumerInfo; 041import org.apache.activemq.command.Message; 042import org.apache.activemq.command.MessageAck; 043import org.apache.activemq.command.MessageDispatchNotification; 044import org.apache.activemq.command.MessagePull; 045import org.apache.activemq.command.ProducerInfo; 046import org.apache.activemq.command.RemoveSubscriptionInfo; 047import org.apache.activemq.command.Response; 048import org.apache.activemq.filter.DestinationFilter; 049import org.apache.activemq.filter.DestinationMap; 050import org.apache.activemq.security.SecurityContext; 051import org.apache.activemq.thread.TaskRunnerFactory; 052import org.apache.activemq.usage.SystemUsage; 053import org.apache.activemq.DestinationDoesNotExistException; 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 destinations.put(destination, dest); 163 updateRegionDestCounts(destination, 1); 164 destinationMap.put(destination, dest); 165 addSubscriptionsForDestination(context, 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 * Updates the counts in RegionStatistics based on whether or not the destination 183 * is an Advisory Destination or not 184 * 185 * @param destination the destination being used to determine which counters to update 186 * @param count the count to add to the counters 187 */ 188 protected void updateRegionDestCounts(ActiveMQDestination destination, int count) { 189 if (destination != null) { 190 if (AdvisorySupport.isAdvisoryTopic(destination)) { 191 regionStatistics.getAdvisoryDestinations().add(count); 192 } else { 193 regionStatistics.getDestinations().add(count); 194 } 195 regionStatistics.getAllDestinations().add(count); 196 } 197 } 198 199 /** 200 * This method checks whether or not the destination can be created based on 201 * {@link PolicyEntry#getMaxDestinations}, if it has been set. Advisory 202 * topics are ignored. 203 * 204 * @param destination 205 * @throws Exception 206 */ 207 protected void validateMaxDestinations(ActiveMQDestination destination) 208 throws Exception { 209 if (broker.getDestinationPolicy() != null) { 210 PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination); 211 // Make sure the destination is not an advisory topic 212 if (entry != null && entry.getMaxDestinations() >= 0 213 && !AdvisorySupport.isAdvisoryTopic(destination)) { 214 // If there is an entry for this destination, look up the set of 215 // destinations associated with this policy 216 // If a destination isn't specified, then just count up 217 // non-advisory destinations (ie count all destinations) 218 int destinationSize = (int) (entry.getDestination() != null ? 219 destinationMap.get(entry.getDestination()).size() : regionStatistics.getDestinations().getCount()); 220 if (destinationSize >= entry.getMaxDestinations()) { 221 if (entry.getDestination() != null) { 222 throw new IllegalStateException( 223 "The maxmimum number of destinations allowed ("+ entry.getMaxDestinations() + 224 ") for the policy " + entry.getDestination() + " has already been reached."); 225 // No destination has been set (default policy) 226 } else { 227 throw new IllegalStateException("The maxmimum number of destinations allowed (" 228 + entry.getMaxDestinations() + ") has already been reached."); 229 } 230 } 231 } 232 } 233 } 234 235 protected List<Subscription> addSubscriptionsForDestination(ConnectionContext context, Destination dest) throws Exception { 236 List<Subscription> rc = new ArrayList<Subscription>(); 237 // Add all consumers that are interested in the destination. 238 for (Iterator<Subscription> iter = subscriptions.values().iterator(); iter.hasNext();) { 239 Subscription sub = iter.next(); 240 if (sub.matches(dest.getActiveMQDestination())) { 241 try { 242 ConnectionContext originalContext = sub.getContext() != null ? sub.getContext() : context; 243 dest.addSubscription(originalContext, sub); 244 rc.add(sub); 245 } catch (SecurityException e) { 246 if (sub.isWildcard()) { 247 LOG.debug("Subscription denied for " + sub + " to destination " + 248 dest.getActiveMQDestination() + ": " + e.getMessage()); 249 } else { 250 throw e; 251 } 252 } 253 } 254 } 255 return rc; 256 257 } 258 259 @Override 260 public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) 261 throws Exception { 262 263 // No timeout.. then try to shut down right way, fails if there are 264 // current subscribers. 265 if (timeout == 0) { 266 for (Iterator<Subscription> iter = subscriptions.values().iterator(); iter.hasNext();) { 267 Subscription sub = iter.next(); 268 if (sub.matches(destination)) { 269 throw new JMSException("Destination still has an active subscription: " + destination); 270 } 271 } 272 } 273 274 if (timeout > 0) { 275 // TODO: implement a way to notify the subscribers that we want to 276 // take the down 277 // the destination and that they should un-subscribe.. Then wait up 278 // to timeout time before 279 // dropping the subscription. 280 } 281 282 LOG.debug("{} removing destination: {}", broker.getBrokerName(), destination); 283 284 destinationsLock.writeLock().lock(); 285 try { 286 Destination dest = destinations.remove(destination); 287 if (dest != null) { 288 updateRegionDestCounts(destination, -1); 289 290 // timeout<0 or we timed out, we now force any remaining 291 // subscriptions to un-subscribe. 292 for (Iterator<Subscription> iter = subscriptions.values().iterator(); iter.hasNext();) { 293 Subscription sub = iter.next(); 294 if (sub.matches(destination)) { 295 dest.removeSubscription(context, sub, 0l); 296 } 297 } 298 destinationMap.removeAll(destination); 299 dispose(context, dest); 300 DestinationInterceptor destinationInterceptor = broker.getDestinationInterceptor(); 301 if (destinationInterceptor != null) { 302 destinationInterceptor.remove(dest); 303 } 304 305 } else { 306 LOG.debug("Cannot remove a destination that doesn't exist: {}", destination); 307 } 308 } finally { 309 destinationsLock.writeLock().unlock(); 310 } 311 } 312 313 /** 314 * Provide an exact or wildcard lookup of destinations in the region 315 * 316 * @return a set of matching destination objects. 317 */ 318 @Override 319 @SuppressWarnings("unchecked") 320 public Set<Destination> getDestinations(ActiveMQDestination destination) { 321 destinationsLock.readLock().lock(); 322 try{ 323 return destinationMap.get(destination); 324 } finally { 325 destinationsLock.readLock().unlock(); 326 } 327 } 328 329 @Override 330 public Map<ActiveMQDestination, Destination> getDestinationMap() { 331 return destinations; 332 } 333 334 @Override 335 @SuppressWarnings("unchecked") 336 public Subscription addConsumer(ConnectionContext context, ConsumerInfo info) throws Exception { 337 LOG.debug("{} adding consumer: {} for destination: {}", new Object[]{ broker.getBrokerName(), info.getConsumerId(), info.getDestination() }); 338 ActiveMQDestination destination = info.getDestination(); 339 if (destination != null && !destination.isPattern() && !destination.isComposite()) { 340 // lets auto-create the destination 341 lookup(context, destination,true); 342 } 343 344 Object addGuard; 345 synchronized (consumerChangeMutexMap) { 346 addGuard = consumerChangeMutexMap.get(info.getConsumerId()); 347 if (addGuard == null) { 348 addGuard = new Object(); 349 consumerChangeMutexMap.put(info.getConsumerId(), addGuard); 350 } 351 } 352 synchronized (addGuard) { 353 Subscription o = subscriptions.get(info.getConsumerId()); 354 if (o != null) { 355 LOG.warn("A duplicate subscription was detected. Clients may be misbehaving. Later warnings you may see about subscription removal are a consequence of this."); 356 return o; 357 } 358 359 // We may need to add some destinations that are in persistent store 360 // but not active 361 // in the broker. 362 // 363 // TODO: think about this a little more. This is good cause 364 // destinations are not loaded into 365 // memory until a client needs to use the queue, but a management 366 // agent viewing the 367 // broker will not see a destination that exists in persistent 368 // store. We may want to 369 // eagerly load all destinations into the broker but have an 370 // inactive state for the 371 // destination which has reduced memory usage. 372 // 373 DestinationFilter.parseFilter(info.getDestination()); 374 375 Subscription sub = createSubscription(context, info); 376 377 // At this point we're done directly manipulating subscriptions, 378 // but we need to retain the synchronized block here. Consider 379 // otherwise what would happen if at this point a second 380 // thread added, then removed, as would be allowed with 381 // no mutex held. Remove is only essentially run once 382 // so everything after this point would be leaked. 383 384 // Add the subscription to all the matching queues. 385 // But copy the matches first - to prevent deadlocks 386 List<Destination> addList = new ArrayList<Destination>(); 387 destinationsLock.readLock().lock(); 388 try { 389 for (Destination dest : (Set<Destination>) destinationMap.get(info.getDestination())) { 390 addList.add(dest); 391 } 392 } finally { 393 destinationsLock.readLock().unlock(); 394 } 395 396 List<Destination> removeList = new ArrayList<Destination>(); 397 for (Destination dest : addList) { 398 try { 399 dest.addSubscription(context, sub); 400 removeList.add(dest); 401 } catch (SecurityException e){ 402 if (sub.isWildcard()) { 403 LOG.debug("Subscription denied for " + sub + " to destination " + 404 dest.getActiveMQDestination() + ": " + e.getMessage()); 405 } else { 406 // remove partial subscriptions 407 for (Destination remove : removeList) { 408 try { 409 remove.removeSubscription(context, sub, info.getLastDeliveredSequenceId()); 410 } catch (Exception ex) { 411 LOG.error("Error unsubscribing " + sub + " from " + remove + ": " + ex.getMessage(), ex); 412 } 413 } 414 throw e; 415 } 416 } 417 } 418 removeList.clear(); 419 420 if (info.isBrowser()) { 421 ((QueueBrowserSubscription) sub).destinationsAdded(); 422 } 423 424 subscriptions.put(info.getConsumerId(), sub); 425 426 return sub; 427 } 428 } 429 430 /** 431 * Get all the Destinations that are in storage 432 * 433 * @return Set of all stored destinations 434 */ 435 @SuppressWarnings("rawtypes") 436 public Set getDurableDestinations() { 437 return destinationFactory.getDestinations(); 438 } 439 440 /** 441 * @return all Destinations that don't have active consumers 442 */ 443 protected Set<ActiveMQDestination> getInactiveDestinations() { 444 Set<ActiveMQDestination> inactiveDests = destinationFactory.getDestinations(); 445 destinationsLock.readLock().lock(); 446 try { 447 inactiveDests.removeAll(destinations.keySet()); 448 } finally { 449 destinationsLock.readLock().unlock(); 450 } 451 return inactiveDests; 452 } 453 454 @Override 455 @SuppressWarnings("unchecked") 456 public void removeConsumer(ConnectionContext context, ConsumerInfo info) throws Exception { 457 LOG.debug("{} removing consumer: {} for destination: {}", new Object[]{ broker.getBrokerName(), info.getConsumerId(), info.getDestination() }); 458 459 Subscription sub = subscriptions.remove(info.getConsumerId()); 460 // The sub could be removed elsewhere - see ConnectionSplitBroker 461 if (sub != null) { 462 463 // remove the subscription from all the matching queues. 464 List<Destination> removeList = new ArrayList<Destination>(); 465 destinationsLock.readLock().lock(); 466 try { 467 for (Destination dest : (Set<Destination>) destinationMap.get(info.getDestination())) { 468 removeList.add(dest); 469 } 470 } finally { 471 destinationsLock.readLock().unlock(); 472 } 473 for (Destination dest : removeList) { 474 dest.removeSubscription(context, sub, info.getLastDeliveredSequenceId()); 475 } 476 477 destroySubscription(sub); 478 } 479 synchronized (consumerChangeMutexMap) { 480 consumerChangeMutexMap.remove(info.getConsumerId()); 481 } 482 } 483 484 protected void destroySubscription(Subscription sub) { 485 sub.destroy(); 486 } 487 488 @Override 489 public void removeSubscription(ConnectionContext context, RemoveSubscriptionInfo info) throws Exception { 490 throw new JMSException("Invalid operation."); 491 } 492 493 @Override 494 public void send(final ProducerBrokerExchange producerExchange, Message messageSend) throws Exception { 495 final ConnectionContext context = producerExchange.getConnectionContext(); 496 497 if (producerExchange.isMutable() || producerExchange.getRegionDestination() == null) { 498 final Destination regionDestination = lookup(context, messageSend.getDestination(),false); 499 producerExchange.setRegionDestination(regionDestination); 500 } 501 502 producerExchange.getRegionDestination().send(producerExchange, messageSend); 503 504 if (producerExchange.getProducerState() != null && producerExchange.getProducerState().getInfo() != null){ 505 producerExchange.getProducerState().getInfo().incrementSentCount(); 506 } 507 } 508 509 @Override 510 public void acknowledge(ConsumerBrokerExchange consumerExchange, MessageAck ack) throws Exception { 511 Subscription sub = consumerExchange.getSubscription(); 512 if (sub == null) { 513 sub = subscriptions.get(ack.getConsumerId()); 514 if (sub == null) { 515 if (!consumerExchange.getConnectionContext().isInRecoveryMode()) { 516 LOG.warn("Ack for non existent subscription, ack: {}", ack); 517 throw new IllegalArgumentException("The subscription does not exist: " + ack.getConsumerId()); 518 } else { 519 LOG.debug("Ack for non existent subscription in recovery, ack: {}", ack); 520 return; 521 } 522 } 523 consumerExchange.setSubscription(sub); 524 } 525 sub.acknowledge(consumerExchange.getConnectionContext(), ack); 526 } 527 528 @Override 529 public Response messagePull(ConnectionContext context, MessagePull pull) throws Exception { 530 Subscription sub = subscriptions.get(pull.getConsumerId()); 531 if (sub == null) { 532 throw new IllegalArgumentException("The subscription does not exist: " + pull.getConsumerId()); 533 } 534 return sub.pullMessage(context, pull); 535 } 536 537 protected Destination lookup(ConnectionContext context, ActiveMQDestination destination,boolean createTemporary) throws Exception { 538 Destination dest = null; 539 540 destinationsLock.readLock().lock(); 541 try { 542 dest = destinations.get(destination); 543 } finally { 544 destinationsLock.readLock().unlock(); 545 } 546 547 if (dest == null) { 548 if (isAutoCreateDestinations()) { 549 // Try to auto create the destination... re-invoke broker 550 // from the 551 // top so that the proper security checks are performed. 552 context.getBroker().addDestination(context, destination, createTemporary); 553 dest = addDestination(context, destination, false); 554 // We should now have the dest created. 555 destinationsLock.readLock().lock(); 556 try { 557 dest = destinations.get(destination); 558 } finally { 559 destinationsLock.readLock().unlock(); 560 } 561 } 562 563 if (dest == null) { 564 throw new JMSException("The destination " + destination + " does not exist."); 565 } 566 } 567 return dest; 568 } 569 570 @Override 571 public void processDispatchNotification(MessageDispatchNotification messageDispatchNotification) throws Exception { 572 Subscription sub = subscriptions.get(messageDispatchNotification.getConsumerId()); 573 if (sub != null) { 574 sub.processMessageDispatchNotification(messageDispatchNotification); 575 } else { 576 throw new JMSException("Slave broker out of sync with master - Subscription: " 577 + messageDispatchNotification.getConsumerId() + " on " 578 + messageDispatchNotification.getDestination() + " does not exist for dispatch of message: " 579 + messageDispatchNotification.getMessageId()); 580 } 581 } 582 583 /* 584 * For a Queue/TempQueue, dispatch order is imperative to match acks, so the 585 * dispatch is deferred till the notification to ensure that the 586 * subscription chosen by the master is used. AMQ-2102 587 */ 588 protected void processDispatchNotificationViaDestination(MessageDispatchNotification messageDispatchNotification) 589 throws Exception { 590 Destination dest = null; 591 destinationsLock.readLock().lock(); 592 try { 593 dest = destinations.get(messageDispatchNotification.getDestination()); 594 } finally { 595 destinationsLock.readLock().unlock(); 596 } 597 598 if (dest != null) { 599 dest.processDispatchNotification(messageDispatchNotification); 600 } else { 601 throw new JMSException("Slave broker out of sync with master - Destination: " 602 + messageDispatchNotification.getDestination() + " does not exist for consumer " 603 + messageDispatchNotification.getConsumerId() + " with message: " 604 + messageDispatchNotification.getMessageId()); 605 } 606 } 607 608 @Override 609 public void gc() { 610 for (Subscription sub : subscriptions.values()) { 611 sub.gc(); 612 } 613 614 destinationsLock.readLock().lock(); 615 try { 616 for (Destination dest : destinations.values()) { 617 dest.gc(); 618 } 619 } finally { 620 destinationsLock.readLock().unlock(); 621 } 622 } 623 624 protected abstract Subscription createSubscription(ConnectionContext context, ConsumerInfo info) throws Exception; 625 626 protected Destination createDestination(ConnectionContext context, ActiveMQDestination destination) 627 throws Exception { 628 return destinationFactory.createDestination(context, destination, destinationStatistics); 629 } 630 631 public boolean isAutoCreateDestinations() { 632 return autoCreateDestinations; 633 } 634 635 public void setAutoCreateDestinations(boolean autoCreateDestinations) { 636 this.autoCreateDestinations = autoCreateDestinations; 637 } 638 639 @Override 640 @SuppressWarnings("unchecked") 641 public void addProducer(ConnectionContext context, ProducerInfo info) throws Exception { 642 destinationsLock.readLock().lock(); 643 try { 644 for (Destination dest : (Set<Destination>) destinationMap.get(info.getDestination())) { 645 dest.addProducer(context, info); 646 } 647 } finally { 648 destinationsLock.readLock().unlock(); 649 } 650 } 651 652 /** 653 * Removes a Producer. 654 * 655 * @param context 656 * the environment the operation is being executed under. 657 * @throws Exception 658 * TODO 659 */ 660 @Override 661 @SuppressWarnings("unchecked") 662 public void removeProducer(ConnectionContext context, ProducerInfo info) throws Exception { 663 destinationsLock.readLock().lock(); 664 try { 665 for (Destination dest : (Set<Destination>) destinationMap.get(info.getDestination())) { 666 dest.removeProducer(context, info); 667 } 668 } finally { 669 destinationsLock.readLock().unlock(); 670 } 671 } 672 673 protected void dispose(ConnectionContext context, Destination dest) throws Exception { 674 dest.dispose(context); 675 dest.stop(); 676 destinationFactory.removeDestination(dest); 677 } 678 679 @Override 680 public void processConsumerControl(ConsumerBrokerExchange consumerExchange, ConsumerControl control) { 681 Subscription sub = subscriptions.get(control.getConsumerId()); 682 if (sub != null && sub instanceof AbstractSubscription) { 683 ((AbstractSubscription) sub).setPrefetchSize(control.getPrefetch()); 684 if (broker.getDestinationPolicy() != null) { 685 PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(control.getDestination()); 686 if (entry != null) { 687 entry.configurePrefetch(sub); 688 } 689 } 690 LOG.debug("setting prefetch: {}, on subscription: {}; resulting value: {}", new Object[]{ control.getPrefetch(), control.getConsumerId(), sub.getConsumerInfo().getCurrentPrefetchSize()}); 691 try { 692 lookup(consumerExchange.getConnectionContext(), control.getDestination(),false).wakeup(); 693 } catch (Exception e) { 694 LOG.warn("failed to deliver post consumerControl dispatch-wakeup, to destination: {}", control.getDestination(), e); 695 } 696 } 697 } 698 699 @Override 700 public void reapplyInterceptor() { 701 destinationsLock.writeLock().lock(); 702 try { 703 DestinationInterceptor destinationInterceptor = broker.getDestinationInterceptor(); 704 Map<ActiveMQDestination, Destination> map = getDestinationMap(); 705 for (ActiveMQDestination key : map.keySet()) { 706 Destination destination = map.get(key); 707 if (destination instanceof CompositeDestinationFilter) { 708 destination = ((CompositeDestinationFilter) destination).next; 709 } 710 if (destinationInterceptor != null) { 711 destination = destinationInterceptor.intercept(destination); 712 } 713 getDestinationMap().put(key, destination); 714 Destination prev = destinations.put(key, destination); 715 if (prev == null) { 716 updateRegionDestCounts(key, 1); 717 } 718 } 719 } finally { 720 destinationsLock.writeLock().unlock(); 721 } 722 } 723}