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; 018 019import java.io.BufferedReader; 020import java.io.File; 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.InputStreamReader; 024import java.net.URI; 025import java.net.URISyntaxException; 026import java.net.UnknownHostException; 027import java.security.Provider; 028import java.security.Security; 029import java.util.ArrayList; 030import java.util.Date; 031import java.util.HashMap; 032import java.util.HashSet; 033import java.util.Iterator; 034import java.util.List; 035import java.util.Locale; 036import java.util.Map; 037import java.util.Set; 038import java.util.concurrent.CopyOnWriteArrayList; 039import java.util.concurrent.CountDownLatch; 040import java.util.concurrent.LinkedBlockingQueue; 041import java.util.concurrent.RejectedExecutionException; 042import java.util.concurrent.RejectedExecutionHandler; 043import java.util.concurrent.SynchronousQueue; 044import java.util.concurrent.ThreadFactory; 045import java.util.concurrent.ThreadPoolExecutor; 046import java.util.concurrent.TimeUnit; 047import java.util.concurrent.atomic.AtomicBoolean; 048import java.util.concurrent.atomic.AtomicInteger; 049import java.util.concurrent.atomic.AtomicLong; 050 051import javax.annotation.PostConstruct; 052import javax.annotation.PreDestroy; 053import javax.management.MalformedObjectNameException; 054import javax.management.ObjectName; 055 056import org.apache.activemq.ActiveMQConnectionMetaData; 057import org.apache.activemq.ConfigurationException; 058import org.apache.activemq.Service; 059import org.apache.activemq.advisory.AdvisoryBroker; 060import org.apache.activemq.broker.cluster.ConnectionSplitBroker; 061import org.apache.activemq.broker.jmx.AnnotatedMBean; 062import org.apache.activemq.broker.jmx.BrokerMBeanSupport; 063import org.apache.activemq.broker.jmx.BrokerView; 064import org.apache.activemq.broker.jmx.ConnectorView; 065import org.apache.activemq.broker.jmx.ConnectorViewMBean; 066import org.apache.activemq.broker.jmx.HealthView; 067import org.apache.activemq.broker.jmx.HealthViewMBean; 068import org.apache.activemq.broker.jmx.JmsConnectorView; 069import org.apache.activemq.broker.jmx.JobSchedulerView; 070import org.apache.activemq.broker.jmx.JobSchedulerViewMBean; 071import org.apache.activemq.broker.jmx.Log4JConfigView; 072import org.apache.activemq.broker.jmx.ManagedRegionBroker; 073import org.apache.activemq.broker.jmx.ManagementContext; 074import org.apache.activemq.broker.jmx.NetworkConnectorView; 075import org.apache.activemq.broker.jmx.NetworkConnectorViewMBean; 076import org.apache.activemq.broker.jmx.ProxyConnectorView; 077import org.apache.activemq.broker.region.CompositeDestinationInterceptor; 078import org.apache.activemq.broker.region.Destination; 079import org.apache.activemq.broker.region.DestinationFactory; 080import org.apache.activemq.broker.region.DestinationFactoryImpl; 081import org.apache.activemq.broker.region.DestinationInterceptor; 082import org.apache.activemq.broker.region.RegionBroker; 083import org.apache.activemq.broker.region.policy.PolicyMap; 084import org.apache.activemq.broker.region.virtual.MirroredQueue; 085import org.apache.activemq.broker.region.virtual.VirtualDestination; 086import org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor; 087import org.apache.activemq.broker.region.virtual.VirtualTopic; 088import org.apache.activemq.broker.scheduler.JobSchedulerStore; 089import org.apache.activemq.broker.scheduler.SchedulerBroker; 090import org.apache.activemq.broker.scheduler.memory.InMemoryJobSchedulerStore; 091import org.apache.activemq.command.ActiveMQDestination; 092import org.apache.activemq.command.ActiveMQQueue; 093import org.apache.activemq.command.BrokerId; 094import org.apache.activemq.command.ProducerInfo; 095import org.apache.activemq.filter.DestinationFilter; 096import org.apache.activemq.network.ConnectionFilter; 097import org.apache.activemq.network.DiscoveryNetworkConnector; 098import org.apache.activemq.network.NetworkConnector; 099import org.apache.activemq.network.jms.JmsConnector; 100import org.apache.activemq.openwire.OpenWireFormat; 101import org.apache.activemq.proxy.ProxyConnector; 102import org.apache.activemq.security.MessageAuthorizationPolicy; 103import org.apache.activemq.selector.SelectorParser; 104import org.apache.activemq.store.JournaledStore; 105import org.apache.activemq.store.PListStore; 106import org.apache.activemq.store.PersistenceAdapter; 107import org.apache.activemq.store.PersistenceAdapterFactory; 108import org.apache.activemq.store.memory.MemoryPersistenceAdapter; 109import org.apache.activemq.thread.Scheduler; 110import org.apache.activemq.thread.TaskRunnerFactory; 111import org.apache.activemq.transport.TransportFactorySupport; 112import org.apache.activemq.transport.TransportServer; 113import org.apache.activemq.transport.vm.VMTransportFactory; 114import org.apache.activemq.usage.StoreUsage; 115import org.apache.activemq.usage.SystemUsage; 116import org.apache.activemq.usage.Usage; 117import org.apache.activemq.util.BrokerSupport; 118import org.apache.activemq.util.DefaultIOExceptionHandler; 119import org.apache.activemq.util.IOExceptionHandler; 120import org.apache.activemq.util.IOExceptionSupport; 121import org.apache.activemq.util.IOHelper; 122import org.apache.activemq.util.InetAddressUtil; 123import org.apache.activemq.util.ServiceStopper; 124import org.apache.activemq.util.StoreUtil; 125import org.apache.activemq.util.ThreadPoolUtils; 126import org.apache.activemq.util.TimeUtils; 127import org.apache.activemq.util.URISupport; 128import org.slf4j.Logger; 129import org.slf4j.LoggerFactory; 130import org.slf4j.MDC; 131 132/** 133 * Manages the life-cycle of an ActiveMQ Broker. A BrokerService consists of a 134 * number of transport connectors, network connectors and a bunch of properties 135 * which can be used to configure the broker as its lazily created. 136 * 137 * @org.apache.xbean.XBean 138 */ 139public class BrokerService implements Service { 140 public static final String DEFAULT_PORT = "61616"; 141 public static final String LOCAL_HOST_NAME; 142 public static final String BROKER_VERSION; 143 public static final String DEFAULT_BROKER_NAME = "localhost"; 144 public static final int DEFAULT_MAX_FILE_LENGTH = 1024 * 1024 * 32; 145 public static final long DEFAULT_START_TIMEOUT = 600000L; 146 147 private static final Logger LOG = LoggerFactory.getLogger(BrokerService.class); 148 149 @SuppressWarnings("unused") 150 private static final long serialVersionUID = 7353129142305630237L; 151 152 private boolean useJmx = true; 153 private boolean enableStatistics = true; 154 private boolean persistent = true; 155 private boolean populateJMSXUserID; 156 private boolean useAuthenticatedPrincipalForJMSXUserID; 157 private boolean populateUserNameInMBeans; 158 private long mbeanInvocationTimeout = 0; 159 160 private boolean useShutdownHook = true; 161 private boolean useLoggingForShutdownErrors; 162 private boolean shutdownOnMasterFailure; 163 private boolean shutdownOnSlaveFailure; 164 private boolean waitForSlave; 165 private long waitForSlaveTimeout = DEFAULT_START_TIMEOUT; 166 private boolean passiveSlave; 167 private String brokerName = DEFAULT_BROKER_NAME; 168 private File dataDirectoryFile; 169 private File tmpDataDirectory; 170 private Broker broker; 171 private BrokerView adminView; 172 private ManagementContext managementContext; 173 private ObjectName brokerObjectName; 174 private TaskRunnerFactory taskRunnerFactory; 175 private TaskRunnerFactory persistenceTaskRunnerFactory; 176 private SystemUsage systemUsage; 177 private SystemUsage producerSystemUsage; 178 private SystemUsage consumerSystemUsaage; 179 private PersistenceAdapter persistenceAdapter; 180 private PersistenceAdapterFactory persistenceFactory; 181 protected DestinationFactory destinationFactory; 182 private MessageAuthorizationPolicy messageAuthorizationPolicy; 183 private final List<TransportConnector> transportConnectors = new CopyOnWriteArrayList<TransportConnector>(); 184 private final List<NetworkConnector> networkConnectors = new CopyOnWriteArrayList<NetworkConnector>(); 185 private final List<ProxyConnector> proxyConnectors = new CopyOnWriteArrayList<ProxyConnector>(); 186 private final List<JmsConnector> jmsConnectors = new CopyOnWriteArrayList<JmsConnector>(); 187 private final List<Service> services = new ArrayList<Service>(); 188 private transient Thread shutdownHook; 189 private String[] transportConnectorURIs; 190 private String[] networkConnectorURIs; 191 private JmsConnector[] jmsBridgeConnectors; // these are Jms to Jms bridges 192 // to other jms messaging systems 193 private boolean deleteAllMessagesOnStartup; 194 private boolean advisorySupport = true; 195 private URI vmConnectorURI; 196 private String defaultSocketURIString; 197 private PolicyMap destinationPolicy; 198 private final AtomicBoolean started = new AtomicBoolean(false); 199 private final AtomicBoolean stopped = new AtomicBoolean(false); 200 private final AtomicBoolean stopping = new AtomicBoolean(false); 201 private BrokerPlugin[] plugins; 202 private boolean keepDurableSubsActive = true; 203 private boolean useVirtualTopics = true; 204 private boolean useMirroredQueues = false; 205 private boolean useTempMirroredQueues = true; 206 /** 207 * Whether or not virtual destination subscriptions should cause network demand 208 */ 209 private boolean useVirtualDestSubs = false; 210 /** 211 * Whether or no the creation of destinations that match virtual destinations 212 * should cause network demand 213 */ 214 private boolean useVirtualDestSubsOnCreation = false; 215 private BrokerId brokerId; 216 private volatile DestinationInterceptor[] destinationInterceptors; 217 private ActiveMQDestination[] destinations; 218 private PListStore tempDataStore; 219 private int persistenceThreadPriority = Thread.MAX_PRIORITY; 220 private boolean useLocalHostBrokerName; 221 private final CountDownLatch stoppedLatch = new CountDownLatch(1); 222 private final CountDownLatch startedLatch = new CountDownLatch(1); 223 private Broker regionBroker; 224 private int producerSystemUsagePortion = 60; 225 private int consumerSystemUsagePortion = 40; 226 private boolean splitSystemUsageForProducersConsumers; 227 private boolean monitorConnectionSplits = false; 228 private int taskRunnerPriority = Thread.NORM_PRIORITY; 229 private boolean dedicatedTaskRunner; 230 private boolean cacheTempDestinations = false;// useful for failover 231 private int timeBeforePurgeTempDestinations = 5000; 232 private final List<Runnable> shutdownHooks = new ArrayList<Runnable>(); 233 private boolean systemExitOnShutdown; 234 private int systemExitOnShutdownExitCode; 235 private SslContext sslContext; 236 private boolean forceStart = false; 237 private IOExceptionHandler ioExceptionHandler; 238 private boolean schedulerSupport = false; 239 private File schedulerDirectoryFile; 240 private Scheduler scheduler; 241 private ThreadPoolExecutor executor; 242 private int schedulePeriodForDestinationPurge= 0; 243 private int maxPurgedDestinationsPerSweep = 0; 244 private int schedulePeriodForDiskUsageCheck = 0; 245 private int diskUsageCheckRegrowThreshold = -1; 246 private BrokerContext brokerContext; 247 private boolean networkConnectorStartAsync = false; 248 private boolean allowTempAutoCreationOnSend; 249 private JobSchedulerStore jobSchedulerStore; 250 private final AtomicLong totalConnections = new AtomicLong(); 251 private final AtomicInteger currentConnections = new AtomicInteger(); 252 253 private long offlineDurableSubscriberTimeout = -1; 254 private long offlineDurableSubscriberTaskSchedule = 300000; 255 private DestinationFilter virtualConsumerDestinationFilter; 256 257 private final AtomicBoolean persistenceAdapterStarted = new AtomicBoolean(false); 258 private Throwable startException = null; 259 private boolean startAsync = false; 260 private Date startDate; 261 private boolean slave = true; 262 263 private boolean restartAllowed = true; 264 private boolean restartRequested = false; 265 private boolean rejectDurableConsumers = false; 266 267 private int storeOpenWireVersion = OpenWireFormat.DEFAULT_STORE_VERSION; 268 269 static { 270 271 try { 272 ClassLoader loader = BrokerService.class.getClassLoader(); 273 Class<?> clazz = loader.loadClass("org.bouncycastle.jce.provider.BouncyCastleProvider"); 274 Provider bouncycastle = (Provider) clazz.newInstance(); 275 Security.insertProviderAt(bouncycastle, 2); 276 LOG.info("Loaded the Bouncy Castle security provider."); 277 } catch(Throwable e) { 278 // No BouncyCastle found so we use the default Java Security Provider 279 } 280 281 String localHostName = "localhost"; 282 try { 283 localHostName = InetAddressUtil.getLocalHostName(); 284 } catch (UnknownHostException e) { 285 LOG.error("Failed to resolve localhost"); 286 } 287 LOCAL_HOST_NAME = localHostName; 288 289 String version = null; 290 try(InputStream in = BrokerService.class.getResourceAsStream("/org/apache/activemq/version.txt")) { 291 if (in != null) { 292 try(InputStreamReader isr = new InputStreamReader(in); 293 BufferedReader reader = new BufferedReader(isr)) { 294 version = reader.readLine(); 295 } 296 } 297 } catch (IOException ie) { 298 LOG.warn("Error reading broker version ", ie); 299 } 300 BROKER_VERSION = version; 301 } 302 303 @Override 304 public String toString() { 305 return "BrokerService[" + getBrokerName() + "]"; 306 } 307 308 private String getBrokerVersion() { 309 String version = ActiveMQConnectionMetaData.PROVIDER_VERSION; 310 if (version == null) { 311 version = BROKER_VERSION; 312 } 313 314 return version; 315 } 316 317 /** 318 * Adds a new transport connector for the given bind address 319 * 320 * @return the newly created and added transport connector 321 * @throws Exception 322 */ 323 public TransportConnector addConnector(String bindAddress) throws Exception { 324 return addConnector(new URI(bindAddress)); 325 } 326 327 /** 328 * Adds a new transport connector for the given bind address 329 * 330 * @return the newly created and added transport connector 331 * @throws Exception 332 */ 333 public TransportConnector addConnector(URI bindAddress) throws Exception { 334 return addConnector(createTransportConnector(bindAddress)); 335 } 336 337 /** 338 * Adds a new transport connector for the given TransportServer transport 339 * 340 * @return the newly created and added transport connector 341 * @throws Exception 342 */ 343 public TransportConnector addConnector(TransportServer transport) throws Exception { 344 return addConnector(new TransportConnector(transport)); 345 } 346 347 /** 348 * Adds a new transport connector 349 * 350 * @return the transport connector 351 * @throws Exception 352 */ 353 public TransportConnector addConnector(TransportConnector connector) throws Exception { 354 transportConnectors.add(connector); 355 return connector; 356 } 357 358 /** 359 * Stops and removes a transport connector from the broker. 360 * 361 * @param connector 362 * @return true if the connector has been previously added to the broker 363 * @throws Exception 364 */ 365 public boolean removeConnector(TransportConnector connector) throws Exception { 366 boolean rc = transportConnectors.remove(connector); 367 if (rc) { 368 unregisterConnectorMBean(connector); 369 } 370 return rc; 371 } 372 373 /** 374 * Adds a new network connector using the given discovery address 375 * 376 * @return the newly created and added network connector 377 * @throws Exception 378 */ 379 public NetworkConnector addNetworkConnector(String discoveryAddress) throws Exception { 380 return addNetworkConnector(new URI(discoveryAddress)); 381 } 382 383 /** 384 * Adds a new proxy connector using the given bind address 385 * 386 * @return the newly created and added network connector 387 * @throws Exception 388 */ 389 public ProxyConnector addProxyConnector(String bindAddress) throws Exception { 390 return addProxyConnector(new URI(bindAddress)); 391 } 392 393 /** 394 * Adds a new network connector using the given discovery address 395 * 396 * @return the newly created and added network connector 397 * @throws Exception 398 */ 399 public NetworkConnector addNetworkConnector(URI discoveryAddress) throws Exception { 400 NetworkConnector connector = new DiscoveryNetworkConnector(discoveryAddress); 401 return addNetworkConnector(connector); 402 } 403 404 /** 405 * Adds a new proxy connector using the given bind address 406 * 407 * @return the newly created and added network connector 408 * @throws Exception 409 */ 410 public ProxyConnector addProxyConnector(URI bindAddress) throws Exception { 411 ProxyConnector connector = new ProxyConnector(); 412 connector.setBind(bindAddress); 413 connector.setRemote(new URI("fanout:multicast://default")); 414 return addProxyConnector(connector); 415 } 416 417 /** 418 * Adds a new network connector to connect this broker to a federated 419 * network 420 */ 421 public NetworkConnector addNetworkConnector(NetworkConnector connector) throws Exception { 422 connector.setBrokerService(this); 423 connector.setLocalUri(getVmConnectorURI()); 424 // Set a connection filter so that the connector does not establish loop 425 // back connections. 426 connector.setConnectionFilter(new ConnectionFilter() { 427 @Override 428 public boolean connectTo(URI location) { 429 List<TransportConnector> transportConnectors = getTransportConnectors(); 430 for (Iterator<TransportConnector> iter = transportConnectors.iterator(); iter.hasNext();) { 431 try { 432 TransportConnector tc = iter.next(); 433 if (location.equals(tc.getConnectUri())) { 434 return false; 435 } 436 } catch (Throwable e) { 437 } 438 } 439 return true; 440 } 441 }); 442 networkConnectors.add(connector); 443 return connector; 444 } 445 446 /** 447 * Removes the given network connector without stopping it. The caller 448 * should call {@link NetworkConnector#stop()} to close the connector 449 */ 450 public boolean removeNetworkConnector(NetworkConnector connector) { 451 boolean answer = networkConnectors.remove(connector); 452 if (answer) { 453 unregisterNetworkConnectorMBean(connector); 454 } 455 return answer; 456 } 457 458 public ProxyConnector addProxyConnector(ProxyConnector connector) throws Exception { 459 URI uri = getVmConnectorURI(); 460 connector.setLocalUri(uri); 461 proxyConnectors.add(connector); 462 if (isUseJmx()) { 463 registerProxyConnectorMBean(connector); 464 } 465 return connector; 466 } 467 468 public JmsConnector addJmsConnector(JmsConnector connector) throws Exception { 469 connector.setBrokerService(this); 470 jmsConnectors.add(connector); 471 if (isUseJmx()) { 472 registerJmsConnectorMBean(connector); 473 } 474 return connector; 475 } 476 477 public JmsConnector removeJmsConnector(JmsConnector connector) { 478 if (jmsConnectors.remove(connector)) { 479 return connector; 480 } 481 return null; 482 } 483 484 public void masterFailed() { 485 if (shutdownOnMasterFailure) { 486 LOG.error("The Master has failed ... shutting down"); 487 try { 488 stop(); 489 } catch (Exception e) { 490 LOG.error("Failed to stop for master failure", e); 491 } 492 } else { 493 LOG.warn("Master Failed - starting all connectors"); 494 try { 495 startAllConnectors(); 496 broker.nowMasterBroker(); 497 } catch (Exception e) { 498 LOG.error("Failed to startAllConnectors", e); 499 } 500 } 501 } 502 503 public String getUptime() { 504 long delta = getUptimeMillis(); 505 506 if (delta == 0) { 507 return "not started"; 508 } 509 510 return TimeUtils.printDuration(delta); 511 } 512 513 public long getUptimeMillis() { 514 if (startDate == null) { 515 return 0; 516 } 517 518 return new Date().getTime() - startDate.getTime(); 519 } 520 521 public boolean isStarted() { 522 return started.get() && startedLatch.getCount() == 0; 523 } 524 525 /** 526 * Forces a start of the broker. 527 * By default a BrokerService instance that was 528 * previously stopped using BrokerService.stop() cannot be restarted 529 * using BrokerService.start(). 530 * This method enforces a restart. 531 * It is not recommended to force a restart of the broker and will not work 532 * for most but some very trivial broker configurations. 533 * For restarting a broker instance we recommend to first call stop() on 534 * the old instance and then recreate a new BrokerService instance. 535 * 536 * @param force - if true enforces a restart. 537 * @throws Exception 538 */ 539 public void start(boolean force) throws Exception { 540 forceStart = force; 541 stopped.set(false); 542 started.set(false); 543 start(); 544 } 545 546 // Service interface 547 // ------------------------------------------------------------------------- 548 549 protected boolean shouldAutostart() { 550 return true; 551 } 552 553 /** 554 * JSR-250 callback wrapper; converts checked exceptions to runtime exceptions 555 * 556 * delegates to autoStart, done to prevent backwards incompatible signature change 557 */ 558 @PostConstruct 559 private void postConstruct() { 560 try { 561 autoStart(); 562 } catch (Exception ex) { 563 throw new RuntimeException(ex); 564 } 565 } 566 567 /** 568 * 569 * @throws Exception 570 * @org. apache.xbean.InitMethod 571 */ 572 public void autoStart() throws Exception { 573 if(shouldAutostart()) { 574 start(); 575 } 576 } 577 578 @Override 579 public void start() throws Exception { 580 if (stopped.get() || !started.compareAndSet(false, true)) { 581 // lets just ignore redundant start() calls 582 // as its way too easy to not be completely sure if start() has been 583 // called or not with the gazillion of different configuration 584 // mechanisms 585 // throw new IllegalStateException("Already started."); 586 return; 587 } 588 589 stopping.set(false); 590 startDate = new Date(); 591 MDC.put("activemq.broker", brokerName); 592 593 try { 594 if (systemExitOnShutdown && useShutdownHook) { 595 throw new ConfigurationException("'useShutdownHook' property cannot be be used with 'systemExitOnShutdown', please turn it off (useShutdownHook=false)"); 596 } 597 processHelperProperties(); 598 if (isUseJmx()) { 599 // need to remove MDC during starting JMX, as that would otherwise causes leaks, as spawned threads inheirt the MDC and 600 // we cannot cleanup clear that during shutdown of the broker. 601 MDC.remove("activemq.broker"); 602 try { 603 startManagementContext(); 604 for (NetworkConnector connector : getNetworkConnectors()) { 605 registerNetworkConnectorMBean(connector); 606 } 607 } finally { 608 MDC.put("activemq.broker", brokerName); 609 } 610 } 611 612 // in jvm master slave, lets not publish over existing broker till we get the lock 613 final BrokerRegistry brokerRegistry = BrokerRegistry.getInstance(); 614 if (brokerRegistry.lookup(getBrokerName()) == null) { 615 brokerRegistry.bind(getBrokerName(), BrokerService.this); 616 } 617 startPersistenceAdapter(startAsync); 618 startBroker(startAsync); 619 brokerRegistry.bind(getBrokerName(), BrokerService.this); 620 } catch (Exception e) { 621 LOG.error("Failed to start Apache ActiveMQ ({}, {})", new Object[]{ getBrokerName(), brokerId }, e); 622 try { 623 if (!stopped.get()) { 624 stop(); 625 } 626 } catch (Exception ex) { 627 LOG.warn("Failed to stop broker after failure in start. This exception will be ignored.", ex); 628 } 629 throw e; 630 } finally { 631 MDC.remove("activemq.broker"); 632 } 633 } 634 635 private void startPersistenceAdapter(boolean async) throws Exception { 636 if (async) { 637 new Thread("Persistence Adapter Starting Thread") { 638 @Override 639 public void run() { 640 try { 641 doStartPersistenceAdapter(); 642 } catch (Throwable e) { 643 startException = e; 644 } finally { 645 synchronized (persistenceAdapterStarted) { 646 persistenceAdapterStarted.set(true); 647 persistenceAdapterStarted.notifyAll(); 648 } 649 } 650 } 651 }.start(); 652 } else { 653 doStartPersistenceAdapter(); 654 } 655 } 656 657 private void doStartPersistenceAdapter() throws Exception { 658 getPersistenceAdapter().setUsageManager(getProducerSystemUsage()); 659 getPersistenceAdapter().setBrokerName(getBrokerName()); 660 LOG.info("Using Persistence Adapter: {}", getPersistenceAdapter()); 661 if (deleteAllMessagesOnStartup) { 662 deleteAllMessages(); 663 } 664 getPersistenceAdapter().start(); 665 666 getJobSchedulerStore(); 667 if (jobSchedulerStore != null) { 668 try { 669 jobSchedulerStore.start(); 670 } catch (Exception e) { 671 RuntimeException exception = new RuntimeException( 672 "Failed to start job scheduler store: " + jobSchedulerStore, e); 673 LOG.error(exception.getLocalizedMessage(), e); 674 throw exception; 675 } 676 } 677 } 678 679 private void startBroker(boolean async) throws Exception { 680 if (async) { 681 new Thread("Broker Starting Thread") { 682 @Override 683 public void run() { 684 try { 685 synchronized (persistenceAdapterStarted) { 686 if (!persistenceAdapterStarted.get()) { 687 persistenceAdapterStarted.wait(); 688 } 689 } 690 doStartBroker(); 691 } catch (Throwable t) { 692 startException = t; 693 } 694 } 695 }.start(); 696 } else { 697 doStartBroker(); 698 } 699 } 700 701 private void doStartBroker() throws Exception { 702 if (startException != null) { 703 return; 704 } 705 startDestinations(); 706 addShutdownHook(); 707 708 broker = getBroker(); 709 brokerId = broker.getBrokerId(); 710 711 // need to log this after creating the broker so we have its id and name 712 LOG.info("Apache ActiveMQ {} ({}, {}) is starting", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId }); 713 broker.start(); 714 715 if (isUseJmx()) { 716 if (getManagementContext().isCreateConnector() && !getManagementContext().isConnectorStarted()) { 717 // try to restart management context 718 // typical for slaves that use the same ports as master 719 managementContext.stop(); 720 startManagementContext(); 721 } 722 ManagedRegionBroker managedBroker = (ManagedRegionBroker) regionBroker; 723 managedBroker.setContextBroker(broker); 724 adminView.setBroker(managedBroker); 725 } 726 727 if (ioExceptionHandler == null) { 728 setIoExceptionHandler(new DefaultIOExceptionHandler()); 729 } 730 731 if (isUseJmx() && Log4JConfigView.isLog4JAvailable()) { 732 ObjectName objectName = BrokerMBeanSupport.createLog4JConfigViewName(getBrokerObjectName().toString()); 733 Log4JConfigView log4jConfigView = new Log4JConfigView(); 734 AnnotatedMBean.registerMBean(getManagementContext(), log4jConfigView, objectName); 735 } 736 737 startAllConnectors(); 738 739 LOG.info("Apache ActiveMQ {} ({}, {}) started", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId}); 740 LOG.info("For help or more information please see: http://activemq.apache.org"); 741 742 getBroker().brokerServiceStarted(); 743 checkSystemUsageLimits(); 744 startedLatch.countDown(); 745 getBroker().nowMasterBroker(); 746 } 747 748 /** 749 * JSR-250 callback wrapper; converts checked exceptions to runtime exceptions 750 * 751 * delegates to stop, done to prevent backwards incompatible signature change 752 */ 753 @PreDestroy 754 private void preDestroy () { 755 try { 756 stop(); 757 } catch (Exception ex) { 758 throw new RuntimeException(); 759 } 760 } 761 762 /** 763 * 764 * @throws Exception 765 * @org.apache .xbean.DestroyMethod 766 */ 767 @Override 768 public void stop() throws Exception { 769 if (!stopping.compareAndSet(false, true)) { 770 LOG.trace("Broker already stopping/stopped"); 771 return; 772 } 773 774 MDC.put("activemq.broker", brokerName); 775 776 if (systemExitOnShutdown) { 777 new Thread() { 778 @Override 779 public void run() { 780 System.exit(systemExitOnShutdownExitCode); 781 } 782 }.start(); 783 } 784 785 LOG.info("Apache ActiveMQ {} ({}, {}) is shutting down", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId} ); 786 787 removeShutdownHook(); 788 if (this.scheduler != null) { 789 this.scheduler.stop(); 790 this.scheduler = null; 791 } 792 ServiceStopper stopper = new ServiceStopper(); 793 if (services != null) { 794 for (Service service : services) { 795 stopper.stop(service); 796 } 797 } 798 stopAllConnectors(stopper); 799 this.slave = true; 800 // remove any VMTransports connected 801 // this has to be done after services are stopped, 802 // to avoid timing issue with discovery (spinning up a new instance) 803 BrokerRegistry.getInstance().unbind(getBrokerName()); 804 VMTransportFactory.stopped(getBrokerName()); 805 if (broker != null) { 806 stopper.stop(broker); 807 broker = null; 808 } 809 810 if (jobSchedulerStore != null) { 811 jobSchedulerStore.stop(); 812 jobSchedulerStore = null; 813 } 814 if (tempDataStore != null) { 815 tempDataStore.stop(); 816 tempDataStore = null; 817 } 818 try { 819 stopper.stop(persistenceAdapter); 820 persistenceAdapter = null; 821 if (isUseJmx()) { 822 stopper.stop(getManagementContext()); 823 managementContext = null; 824 } 825 // Clear SelectorParser cache to free memory 826 SelectorParser.clearCache(); 827 } finally { 828 started.set(false); 829 stopped.set(true); 830 stoppedLatch.countDown(); 831 } 832 833 if (this.taskRunnerFactory != null) { 834 this.taskRunnerFactory.shutdown(); 835 this.taskRunnerFactory = null; 836 } 837 if (this.executor != null) { 838 ThreadPoolUtils.shutdownNow(executor); 839 this.executor = null; 840 } 841 842 this.destinationInterceptors = null; 843 this.destinationFactory = null; 844 845 if (startDate != null) { 846 LOG.info("Apache ActiveMQ {} ({}, {}) uptime {}", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId, getUptime()}); 847 } 848 LOG.info("Apache ActiveMQ {} ({}, {}) is shutdown", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId}); 849 850 synchronized (shutdownHooks) { 851 for (Runnable hook : shutdownHooks) { 852 try { 853 hook.run(); 854 } catch (Throwable e) { 855 stopper.onException(hook, e); 856 } 857 } 858 } 859 860 MDC.remove("activemq.broker"); 861 862 // and clear start date 863 startDate = null; 864 865 stopper.throwFirstException(); 866 } 867 868 public boolean checkQueueSize(String queueName) { 869 long count = 0; 870 long queueSize = 0; 871 Map<ActiveMQDestination, Destination> destinationMap = regionBroker.getDestinationMap(); 872 for (Map.Entry<ActiveMQDestination, Destination> entry : destinationMap.entrySet()) { 873 if (entry.getKey().isQueue()) { 874 if (entry.getValue().getName().matches(queueName)) { 875 queueSize = entry.getValue().getDestinationStatistics().getMessages().getCount(); 876 count += queueSize; 877 if (queueSize > 0) { 878 LOG.info("Queue has pending message: {} queueSize is: {}", entry.getValue().getName(), queueSize); 879 } 880 } 881 } 882 } 883 return count == 0; 884 } 885 886 /** 887 * This method (both connectorName and queueName are using regex to match) 888 * 1. stop the connector (supposed the user input the connector which the 889 * clients connect to) 2. to check whether there is any pending message on 890 * the queues defined by queueName 3. supposedly, after stop the connector, 891 * client should failover to other broker and pending messages should be 892 * forwarded. if no pending messages, the method finally call stop to stop 893 * the broker. 894 * 895 * @param connectorName 896 * @param queueName 897 * @param timeout 898 * @param pollInterval 899 * @throws Exception 900 */ 901 public void stopGracefully(String connectorName, String queueName, long timeout, long pollInterval) throws Exception { 902 if (isUseJmx()) { 903 if (connectorName == null || queueName == null || timeout <= 0) { 904 throw new Exception( 905 "connectorName and queueName cannot be null and timeout should be >0 for stopGracefully."); 906 } 907 if (pollInterval <= 0) { 908 pollInterval = 30; 909 } 910 LOG.info("Stop gracefully with connectorName: {} queueName: {} timeout: {} pollInterval: {}", new Object[]{ 911 connectorName, queueName, timeout, pollInterval 912 }); 913 TransportConnector connector; 914 for (int i = 0; i < transportConnectors.size(); i++) { 915 connector = transportConnectors.get(i); 916 if (connector != null && connector.getName() != null && connector.getName().matches(connectorName)) { 917 connector.stop(); 918 } 919 } 920 long start = System.currentTimeMillis(); 921 while (System.currentTimeMillis() - start < timeout * 1000) { 922 // check quesize until it gets zero 923 if (checkQueueSize(queueName)) { 924 stop(); 925 break; 926 } else { 927 Thread.sleep(pollInterval * 1000); 928 } 929 } 930 if (stopped.get()) { 931 LOG.info("Successfully stop the broker."); 932 } else { 933 LOG.info("There is still pending message on the queue. Please check and stop the broker manually."); 934 } 935 } 936 } 937 938 /** 939 * A helper method to block the caller thread until the broker has been 940 * stopped 941 */ 942 public void waitUntilStopped() { 943 while (isStarted() && !stopped.get()) { 944 try { 945 stoppedLatch.await(); 946 } catch (InterruptedException e) { 947 // ignore 948 } 949 } 950 } 951 952 public boolean isStopped() { 953 return stopped.get(); 954 } 955 956 /** 957 * A helper method to block the caller thread until the broker has fully started 958 * @return boolean true if wait succeeded false if broker was not started or was stopped 959 */ 960 public boolean waitUntilStarted() { 961 return waitUntilStarted(DEFAULT_START_TIMEOUT); 962 } 963 964 /** 965 * A helper method to block the caller thread until the broker has fully started 966 * 967 * @param timeout 968 * the amount of time to wait before giving up and returning false. 969 * 970 * @return boolean true if wait succeeded false if broker was not started or was stopped 971 */ 972 public boolean waitUntilStarted(long timeout) { 973 boolean waitSucceeded = isStarted(); 974 long expiration = Math.max(0, timeout + System.currentTimeMillis()); 975 while (!isStarted() && !stopped.get() && !waitSucceeded && expiration > System.currentTimeMillis()) { 976 try { 977 if (startException != null) { 978 return waitSucceeded; 979 } 980 waitSucceeded = startedLatch.await(100L, TimeUnit.MILLISECONDS); 981 } catch (InterruptedException ignore) { 982 } 983 } 984 return waitSucceeded; 985 } 986 987 // Properties 988 // ------------------------------------------------------------------------- 989 /** 990 * Returns the message broker 991 */ 992 public Broker getBroker() throws Exception { 993 if (broker == null) { 994 broker = createBroker(); 995 } 996 return broker; 997 } 998 999 /** 1000 * Returns the administration view of the broker; used to create and destroy 1001 * resources such as queues and topics. Note this method returns null if JMX 1002 * is disabled. 1003 */ 1004 public BrokerView getAdminView() throws Exception { 1005 if (adminView == null) { 1006 // force lazy creation 1007 getBroker(); 1008 } 1009 return adminView; 1010 } 1011 1012 public void setAdminView(BrokerView adminView) { 1013 this.adminView = adminView; 1014 } 1015 1016 public String getBrokerName() { 1017 return brokerName; 1018 } 1019 1020 /** 1021 * Sets the name of this broker; which must be unique in the network 1022 * 1023 * @param brokerName 1024 */ 1025 public void setBrokerName(String brokerName) { 1026 if (brokerName == null) { 1027 throw new NullPointerException("The broker name cannot be null"); 1028 } 1029 String str = brokerName.replaceAll("[^a-zA-Z0-9\\.\\_\\-\\:]", "_"); 1030 if (!str.equals(brokerName)) { 1031 LOG.error("Broker Name: {} contained illegal characters - replaced with {}", brokerName, str); 1032 } 1033 this.brokerName = str.trim(); 1034 } 1035 1036 public PersistenceAdapterFactory getPersistenceFactory() { 1037 return persistenceFactory; 1038 } 1039 1040 public File getDataDirectoryFile() { 1041 if (dataDirectoryFile == null) { 1042 dataDirectoryFile = new File(IOHelper.getDefaultDataDirectory()); 1043 } 1044 return dataDirectoryFile; 1045 } 1046 1047 public File getBrokerDataDirectory() { 1048 String brokerDir = getBrokerName(); 1049 return new File(getDataDirectoryFile(), brokerDir); 1050 } 1051 1052 /** 1053 * Sets the directory in which the data files will be stored by default for 1054 * the JDBC and Journal persistence adaptors. 1055 * 1056 * @param dataDirectory 1057 * the directory to store data files 1058 */ 1059 public void setDataDirectory(String dataDirectory) { 1060 setDataDirectoryFile(new File(dataDirectory)); 1061 } 1062 1063 /** 1064 * Sets the directory in which the data files will be stored by default for 1065 * the JDBC and Journal persistence adaptors. 1066 * 1067 * @param dataDirectoryFile 1068 * the directory to store data files 1069 */ 1070 public void setDataDirectoryFile(File dataDirectoryFile) { 1071 this.dataDirectoryFile = dataDirectoryFile; 1072 } 1073 1074 /** 1075 * @return the tmpDataDirectory 1076 */ 1077 public File getTmpDataDirectory() { 1078 if (tmpDataDirectory == null) { 1079 tmpDataDirectory = new File(getBrokerDataDirectory(), "tmp_storage"); 1080 } 1081 return tmpDataDirectory; 1082 } 1083 1084 /** 1085 * @param tmpDataDirectory 1086 * the tmpDataDirectory to set 1087 */ 1088 public void setTmpDataDirectory(File tmpDataDirectory) { 1089 this.tmpDataDirectory = tmpDataDirectory; 1090 } 1091 1092 public void setPersistenceFactory(PersistenceAdapterFactory persistenceFactory) { 1093 this.persistenceFactory = persistenceFactory; 1094 } 1095 1096 public void setDestinationFactory(DestinationFactory destinationFactory) { 1097 this.destinationFactory = destinationFactory; 1098 } 1099 1100 public boolean isPersistent() { 1101 return persistent; 1102 } 1103 1104 /** 1105 * Sets whether or not persistence is enabled or disabled. 1106 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1107 */ 1108 public void setPersistent(boolean persistent) { 1109 this.persistent = persistent; 1110 } 1111 1112 public boolean isPopulateJMSXUserID() { 1113 return populateJMSXUserID; 1114 } 1115 1116 /** 1117 * Sets whether or not the broker should populate the JMSXUserID header. 1118 */ 1119 public void setPopulateJMSXUserID(boolean populateJMSXUserID) { 1120 this.populateJMSXUserID = populateJMSXUserID; 1121 } 1122 1123 public SystemUsage getSystemUsage() { 1124 try { 1125 if (systemUsage == null) { 1126 1127 systemUsage = new SystemUsage("Main", getPersistenceAdapter(), getTempDataStore(), getJobSchedulerStore()); 1128 systemUsage.setExecutor(getExecutor()); 1129 systemUsage.getMemoryUsage().setLimit(1024L * 1024 * 1024 * 1); // 1 GB 1130 systemUsage.getTempUsage().setLimit(1024L * 1024 * 1024 * 50); // 50 GB 1131 systemUsage.getStoreUsage().setLimit(1024L * 1024 * 1024 * 100); // 100 GB 1132 systemUsage.getJobSchedulerUsage().setLimit(1024L * 1024 * 1024 * 50); // 50 GB 1133 addService(this.systemUsage); 1134 } 1135 return systemUsage; 1136 } catch (IOException e) { 1137 LOG.error("Cannot create SystemUsage", e); 1138 throw new RuntimeException("Fatally failed to create SystemUsage" + e.getMessage(), e); 1139 } 1140 } 1141 1142 public void setSystemUsage(SystemUsage memoryManager) { 1143 if (this.systemUsage != null) { 1144 removeService(this.systemUsage); 1145 } 1146 this.systemUsage = memoryManager; 1147 if (this.systemUsage.getExecutor()==null) { 1148 this.systemUsage.setExecutor(getExecutor()); 1149 } 1150 addService(this.systemUsage); 1151 } 1152 1153 /** 1154 * @return the consumerUsageManager 1155 * @throws IOException 1156 */ 1157 public SystemUsage getConsumerSystemUsage() throws IOException { 1158 if (this.consumerSystemUsaage == null) { 1159 if (splitSystemUsageForProducersConsumers) { 1160 this.consumerSystemUsaage = new SystemUsage(getSystemUsage(), "Consumer"); 1161 float portion = consumerSystemUsagePortion / 100f; 1162 this.consumerSystemUsaage.getMemoryUsage().setUsagePortion(portion); 1163 addService(this.consumerSystemUsaage); 1164 } else { 1165 consumerSystemUsaage = getSystemUsage(); 1166 } 1167 } 1168 return this.consumerSystemUsaage; 1169 } 1170 1171 /** 1172 * @param consumerSystemUsaage 1173 * the storeSystemUsage to set 1174 */ 1175 public void setConsumerSystemUsage(SystemUsage consumerSystemUsaage) { 1176 if (this.consumerSystemUsaage != null) { 1177 removeService(this.consumerSystemUsaage); 1178 } 1179 this.consumerSystemUsaage = consumerSystemUsaage; 1180 addService(this.consumerSystemUsaage); 1181 } 1182 1183 /** 1184 * @return the producerUsageManager 1185 * @throws IOException 1186 */ 1187 public SystemUsage getProducerSystemUsage() throws IOException { 1188 if (producerSystemUsage == null) { 1189 if (splitSystemUsageForProducersConsumers) { 1190 producerSystemUsage = new SystemUsage(getSystemUsage(), "Producer"); 1191 float portion = producerSystemUsagePortion / 100f; 1192 producerSystemUsage.getMemoryUsage().setUsagePortion(portion); 1193 addService(producerSystemUsage); 1194 } else { 1195 producerSystemUsage = getSystemUsage(); 1196 } 1197 } 1198 return producerSystemUsage; 1199 } 1200 1201 /** 1202 * @param producerUsageManager 1203 * the producerUsageManager to set 1204 */ 1205 public void setProducerSystemUsage(SystemUsage producerUsageManager) { 1206 if (this.producerSystemUsage != null) { 1207 removeService(this.producerSystemUsage); 1208 } 1209 this.producerSystemUsage = producerUsageManager; 1210 addService(this.producerSystemUsage); 1211 } 1212 1213 public PersistenceAdapter getPersistenceAdapter() throws IOException { 1214 if (persistenceAdapter == null) { 1215 persistenceAdapter = createPersistenceAdapter(); 1216 configureService(persistenceAdapter); 1217 this.persistenceAdapter = registerPersistenceAdapterMBean(persistenceAdapter); 1218 } 1219 return persistenceAdapter; 1220 } 1221 1222 /** 1223 * Sets the persistence adaptor implementation to use for this broker 1224 * 1225 * @throws IOException 1226 */ 1227 public void setPersistenceAdapter(PersistenceAdapter persistenceAdapter) throws IOException { 1228 if (!isPersistent() && ! (persistenceAdapter instanceof MemoryPersistenceAdapter)) { 1229 LOG.warn("persistent=\"false\", ignoring configured persistenceAdapter: {}", persistenceAdapter); 1230 return; 1231 } 1232 this.persistenceAdapter = persistenceAdapter; 1233 configureService(this.persistenceAdapter); 1234 this.persistenceAdapter = registerPersistenceAdapterMBean(persistenceAdapter); 1235 } 1236 1237 public TaskRunnerFactory getTaskRunnerFactory() { 1238 if (this.taskRunnerFactory == null) { 1239 this.taskRunnerFactory = new TaskRunnerFactory("ActiveMQ BrokerService["+getBrokerName()+"] Task", getTaskRunnerPriority(), true, 1000, 1240 isDedicatedTaskRunner()); 1241 this.taskRunnerFactory.setThreadClassLoader(this.getClass().getClassLoader()); 1242 } 1243 return this.taskRunnerFactory; 1244 } 1245 1246 public void setTaskRunnerFactory(TaskRunnerFactory taskRunnerFactory) { 1247 this.taskRunnerFactory = taskRunnerFactory; 1248 } 1249 1250 public TaskRunnerFactory getPersistenceTaskRunnerFactory() { 1251 if (taskRunnerFactory == null) { 1252 persistenceTaskRunnerFactory = new TaskRunnerFactory("Persistence Adaptor Task", persistenceThreadPriority, 1253 true, 1000, isDedicatedTaskRunner()); 1254 } 1255 return persistenceTaskRunnerFactory; 1256 } 1257 1258 public void setPersistenceTaskRunnerFactory(TaskRunnerFactory persistenceTaskRunnerFactory) { 1259 this.persistenceTaskRunnerFactory = persistenceTaskRunnerFactory; 1260 } 1261 1262 public boolean isUseJmx() { 1263 return useJmx; 1264 } 1265 1266 public boolean isEnableStatistics() { 1267 return enableStatistics; 1268 } 1269 1270 /** 1271 * Sets whether or not the Broker's services enable statistics or not. 1272 */ 1273 public void setEnableStatistics(boolean enableStatistics) { 1274 this.enableStatistics = enableStatistics; 1275 } 1276 1277 /** 1278 * Sets whether or not the Broker's services should be exposed into JMX or 1279 * not. 1280 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1281 */ 1282 public void setUseJmx(boolean useJmx) { 1283 this.useJmx = useJmx; 1284 } 1285 1286 public ObjectName getBrokerObjectName() throws MalformedObjectNameException { 1287 if (brokerObjectName == null) { 1288 brokerObjectName = createBrokerObjectName(); 1289 } 1290 return brokerObjectName; 1291 } 1292 1293 /** 1294 * Sets the JMX ObjectName for this broker 1295 */ 1296 public void setBrokerObjectName(ObjectName brokerObjectName) { 1297 this.brokerObjectName = brokerObjectName; 1298 } 1299 1300 public ManagementContext getManagementContext() { 1301 if (managementContext == null) { 1302 managementContext = new ManagementContext(); 1303 } 1304 return managementContext; 1305 } 1306 1307 public void setManagementContext(ManagementContext managementContext) { 1308 this.managementContext = managementContext; 1309 } 1310 1311 public NetworkConnector getNetworkConnectorByName(String connectorName) { 1312 for (NetworkConnector connector : networkConnectors) { 1313 if (connector.getName().equals(connectorName)) { 1314 return connector; 1315 } 1316 } 1317 return null; 1318 } 1319 1320 public String[] getNetworkConnectorURIs() { 1321 return networkConnectorURIs; 1322 } 1323 1324 public void setNetworkConnectorURIs(String[] networkConnectorURIs) { 1325 this.networkConnectorURIs = networkConnectorURIs; 1326 } 1327 1328 public TransportConnector getConnectorByName(String connectorName) { 1329 for (TransportConnector connector : transportConnectors) { 1330 if (connector.getName().equals(connectorName)) { 1331 return connector; 1332 } 1333 } 1334 return null; 1335 } 1336 1337 public Map<String, String> getTransportConnectorURIsAsMap() { 1338 Map<String, String> answer = new HashMap<String, String>(); 1339 for (TransportConnector connector : transportConnectors) { 1340 try { 1341 URI uri = connector.getConnectUri(); 1342 if (uri != null) { 1343 String scheme = uri.getScheme(); 1344 if (scheme != null) { 1345 answer.put(scheme.toLowerCase(Locale.ENGLISH), uri.toString()); 1346 } 1347 } 1348 } catch (Exception e) { 1349 LOG.debug("Failed to read URI to build transportURIsAsMap", e); 1350 } 1351 } 1352 return answer; 1353 } 1354 1355 public ProducerBrokerExchange getProducerBrokerExchange(ProducerInfo producerInfo){ 1356 ProducerBrokerExchange result = null; 1357 1358 for (TransportConnector connector : transportConnectors) { 1359 for (TransportConnection tc: connector.getConnections()){ 1360 result = tc.getProducerBrokerExchangeIfExists(producerInfo); 1361 if (result !=null){ 1362 return result; 1363 } 1364 } 1365 } 1366 return result; 1367 } 1368 1369 public String[] getTransportConnectorURIs() { 1370 return transportConnectorURIs; 1371 } 1372 1373 public void setTransportConnectorURIs(String[] transportConnectorURIs) { 1374 this.transportConnectorURIs = transportConnectorURIs; 1375 } 1376 1377 /** 1378 * @return Returns the jmsBridgeConnectors. 1379 */ 1380 public JmsConnector[] getJmsBridgeConnectors() { 1381 return jmsBridgeConnectors; 1382 } 1383 1384 /** 1385 * @param jmsConnectors 1386 * The jmsBridgeConnectors to set. 1387 */ 1388 public void setJmsBridgeConnectors(JmsConnector[] jmsConnectors) { 1389 this.jmsBridgeConnectors = jmsConnectors; 1390 } 1391 1392 public Service[] getServices() { 1393 return services.toArray(new Service[0]); 1394 } 1395 1396 /** 1397 * Sets the services associated with this broker. 1398 */ 1399 public void setServices(Service[] services) { 1400 this.services.clear(); 1401 if (services != null) { 1402 for (int i = 0; i < services.length; i++) { 1403 this.services.add(services[i]); 1404 } 1405 } 1406 } 1407 1408 /** 1409 * Adds a new service so that it will be started as part of the broker 1410 * lifecycle 1411 */ 1412 public void addService(Service service) { 1413 services.add(service); 1414 } 1415 1416 public void removeService(Service service) { 1417 services.remove(service); 1418 } 1419 1420 public boolean isUseLoggingForShutdownErrors() { 1421 return useLoggingForShutdownErrors; 1422 } 1423 1424 /** 1425 * Sets whether or not we should use commons-logging when reporting errors 1426 * when shutting down the broker 1427 */ 1428 public void setUseLoggingForShutdownErrors(boolean useLoggingForShutdownErrors) { 1429 this.useLoggingForShutdownErrors = useLoggingForShutdownErrors; 1430 } 1431 1432 public boolean isUseShutdownHook() { 1433 return useShutdownHook; 1434 } 1435 1436 /** 1437 * Sets whether or not we should use a shutdown handler to close down the 1438 * broker cleanly if the JVM is terminated. It is recommended you leave this 1439 * enabled. 1440 */ 1441 public void setUseShutdownHook(boolean useShutdownHook) { 1442 this.useShutdownHook = useShutdownHook; 1443 } 1444 1445 public boolean isAdvisorySupport() { 1446 return advisorySupport; 1447 } 1448 1449 /** 1450 * Allows the support of advisory messages to be disabled for performance 1451 * reasons. 1452 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1453 */ 1454 public void setAdvisorySupport(boolean advisorySupport) { 1455 this.advisorySupport = advisorySupport; 1456 } 1457 1458 public List<TransportConnector> getTransportConnectors() { 1459 return new ArrayList<TransportConnector>(transportConnectors); 1460 } 1461 1462 /** 1463 * Sets the transport connectors which this broker will listen on for new 1464 * clients 1465 * 1466 * @org.apache.xbean.Property 1467 * nestedType="org.apache.activemq.broker.TransportConnector" 1468 */ 1469 public void setTransportConnectors(List<TransportConnector> transportConnectors) throws Exception { 1470 for (TransportConnector connector : transportConnectors) { 1471 addConnector(connector); 1472 } 1473 } 1474 1475 public TransportConnector getTransportConnectorByName(String name){ 1476 for (TransportConnector transportConnector : transportConnectors){ 1477 if (name.equals(transportConnector.getName())){ 1478 return transportConnector; 1479 } 1480 } 1481 return null; 1482 } 1483 1484 public TransportConnector getTransportConnectorByScheme(String scheme){ 1485 for (TransportConnector transportConnector : transportConnectors){ 1486 if (scheme.equals(transportConnector.getUri().getScheme())){ 1487 return transportConnector; 1488 } 1489 } 1490 return null; 1491 } 1492 1493 public List<NetworkConnector> getNetworkConnectors() { 1494 return new ArrayList<NetworkConnector>(networkConnectors); 1495 } 1496 1497 public List<ProxyConnector> getProxyConnectors() { 1498 return new ArrayList<ProxyConnector>(proxyConnectors); 1499 } 1500 1501 /** 1502 * Sets the network connectors which this broker will use to connect to 1503 * other brokers in a federated network 1504 * 1505 * @org.apache.xbean.Property 1506 * nestedType="org.apache.activemq.network.NetworkConnector" 1507 */ 1508 public void setNetworkConnectors(List<?> networkConnectors) throws Exception { 1509 for (Object connector : networkConnectors) { 1510 addNetworkConnector((NetworkConnector) connector); 1511 } 1512 } 1513 1514 /** 1515 * Sets the network connectors which this broker will use to connect to 1516 * other brokers in a federated network 1517 */ 1518 public void setProxyConnectors(List<?> proxyConnectors) throws Exception { 1519 for (Object connector : proxyConnectors) { 1520 addProxyConnector((ProxyConnector) connector); 1521 } 1522 } 1523 1524 public PolicyMap getDestinationPolicy() { 1525 return destinationPolicy; 1526 } 1527 1528 /** 1529 * Sets the destination specific policies available either for exact 1530 * destinations or for wildcard areas of destinations. 1531 */ 1532 public void setDestinationPolicy(PolicyMap policyMap) { 1533 this.destinationPolicy = policyMap; 1534 } 1535 1536 public BrokerPlugin[] getPlugins() { 1537 return plugins; 1538 } 1539 1540 /** 1541 * Sets a number of broker plugins to install such as for security 1542 * authentication or authorization 1543 */ 1544 public void setPlugins(BrokerPlugin[] plugins) { 1545 this.plugins = plugins; 1546 } 1547 1548 public MessageAuthorizationPolicy getMessageAuthorizationPolicy() { 1549 return messageAuthorizationPolicy; 1550 } 1551 1552 /** 1553 * Sets the policy used to decide if the current connection is authorized to 1554 * consume a given message 1555 */ 1556 public void setMessageAuthorizationPolicy(MessageAuthorizationPolicy messageAuthorizationPolicy) { 1557 this.messageAuthorizationPolicy = messageAuthorizationPolicy; 1558 } 1559 1560 /** 1561 * Delete all messages from the persistent store 1562 * 1563 * @throws IOException 1564 */ 1565 public void deleteAllMessages() throws IOException { 1566 getPersistenceAdapter().deleteAllMessages(); 1567 } 1568 1569 public boolean isDeleteAllMessagesOnStartup() { 1570 return deleteAllMessagesOnStartup; 1571 } 1572 1573 /** 1574 * Sets whether or not all messages are deleted on startup - mostly only 1575 * useful for testing. 1576 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1577 */ 1578 public void setDeleteAllMessagesOnStartup(boolean deletePersistentMessagesOnStartup) { 1579 this.deleteAllMessagesOnStartup = deletePersistentMessagesOnStartup; 1580 } 1581 1582 public URI getVmConnectorURI() { 1583 if (vmConnectorURI == null) { 1584 try { 1585 vmConnectorURI = new URI("vm://" + getBrokerName().replaceAll("[^a-zA-Z0-9\\.\\_\\-]", "_")); 1586 } catch (URISyntaxException e) { 1587 LOG.error("Badly formed URI from {}", getBrokerName(), e); 1588 } 1589 } 1590 return vmConnectorURI; 1591 } 1592 1593 public void setVmConnectorURI(URI vmConnectorURI) { 1594 this.vmConnectorURI = vmConnectorURI; 1595 } 1596 1597 public String getDefaultSocketURIString() { 1598 if (started.get()) { 1599 if (this.defaultSocketURIString == null) { 1600 for (TransportConnector tc:this.transportConnectors) { 1601 String result = null; 1602 try { 1603 result = tc.getPublishableConnectString(); 1604 } catch (Exception e) { 1605 LOG.warn("Failed to get the ConnectURI for {}", tc, e); 1606 } 1607 if (result != null) { 1608 // find first publishable uri 1609 if (tc.isUpdateClusterClients() || tc.isRebalanceClusterClients()) { 1610 this.defaultSocketURIString = result; 1611 break; 1612 } else { 1613 // or use the first defined 1614 if (this.defaultSocketURIString == null) { 1615 this.defaultSocketURIString = result; 1616 } 1617 } 1618 } 1619 } 1620 1621 } 1622 return this.defaultSocketURIString; 1623 } 1624 return null; 1625 } 1626 1627 /** 1628 * @return Returns the shutdownOnMasterFailure. 1629 */ 1630 public boolean isShutdownOnMasterFailure() { 1631 return shutdownOnMasterFailure; 1632 } 1633 1634 /** 1635 * @param shutdownOnMasterFailure 1636 * The shutdownOnMasterFailure to set. 1637 */ 1638 public void setShutdownOnMasterFailure(boolean shutdownOnMasterFailure) { 1639 this.shutdownOnMasterFailure = shutdownOnMasterFailure; 1640 } 1641 1642 public boolean isKeepDurableSubsActive() { 1643 return keepDurableSubsActive; 1644 } 1645 1646 public void setKeepDurableSubsActive(boolean keepDurableSubsActive) { 1647 this.keepDurableSubsActive = keepDurableSubsActive; 1648 } 1649 1650 public boolean isUseVirtualTopics() { 1651 return useVirtualTopics; 1652 } 1653 1654 /** 1655 * Sets whether or not <a 1656 * href="http://activemq.apache.org/virtual-destinations.html">Virtual 1657 * Topics</a> should be supported by default if they have not been 1658 * explicitly configured. 1659 */ 1660 public void setUseVirtualTopics(boolean useVirtualTopics) { 1661 this.useVirtualTopics = useVirtualTopics; 1662 } 1663 1664 public DestinationInterceptor[] getDestinationInterceptors() { 1665 return destinationInterceptors; 1666 } 1667 1668 public boolean isUseMirroredQueues() { 1669 return useMirroredQueues; 1670 } 1671 1672 /** 1673 * Sets whether or not <a 1674 * href="http://activemq.apache.org/mirrored-queues.html">Mirrored 1675 * Queues</a> should be supported by default if they have not been 1676 * explicitly configured. 1677 */ 1678 public void setUseMirroredQueues(boolean useMirroredQueues) { 1679 this.useMirroredQueues = useMirroredQueues; 1680 } 1681 1682 /** 1683 * Sets the destination interceptors to use 1684 */ 1685 public void setDestinationInterceptors(DestinationInterceptor[] destinationInterceptors) { 1686 this.destinationInterceptors = destinationInterceptors; 1687 } 1688 1689 public ActiveMQDestination[] getDestinations() { 1690 return destinations; 1691 } 1692 1693 /** 1694 * Sets the destinations which should be loaded/created on startup 1695 */ 1696 public void setDestinations(ActiveMQDestination[] destinations) { 1697 this.destinations = destinations; 1698 } 1699 1700 /** 1701 * @return the tempDataStore 1702 */ 1703 public synchronized PListStore getTempDataStore() { 1704 if (tempDataStore == null) { 1705 if (!isPersistent()) { 1706 return null; 1707 } 1708 1709 try { 1710 PersistenceAdapter pa = getPersistenceAdapter(); 1711 if( pa!=null && pa instanceof PListStore) { 1712 return (PListStore) pa; 1713 } 1714 } catch (IOException e) { 1715 throw new RuntimeException(e); 1716 } 1717 1718 boolean result = true; 1719 boolean empty = true; 1720 try { 1721 File directory = getTmpDataDirectory(); 1722 if (directory.exists() && directory.isDirectory()) { 1723 File[] files = directory.listFiles(); 1724 if (files != null && files.length > 0) { 1725 empty = false; 1726 for (int i = 0; i < files.length; i++) { 1727 File file = files[i]; 1728 if (!file.isDirectory()) { 1729 result &= file.delete(); 1730 } 1731 } 1732 } 1733 } 1734 if (!empty) { 1735 String str = result ? "Successfully deleted" : "Failed to delete"; 1736 LOG.info("{} temporary storage", str); 1737 } 1738 1739 String clazz = "org.apache.activemq.store.kahadb.plist.PListStoreImpl"; 1740 this.tempDataStore = (PListStore) getClass().getClassLoader().loadClass(clazz).newInstance(); 1741 this.tempDataStore.setDirectory(getTmpDataDirectory()); 1742 configureService(tempDataStore); 1743 this.tempDataStore.start(); 1744 } catch (Exception e) { 1745 throw new RuntimeException(e); 1746 } 1747 } 1748 return tempDataStore; 1749 } 1750 1751 /** 1752 * @param tempDataStore 1753 * the tempDataStore to set 1754 */ 1755 public void setTempDataStore(PListStore tempDataStore) { 1756 this.tempDataStore = tempDataStore; 1757 configureService(tempDataStore); 1758 try { 1759 tempDataStore.start(); 1760 } catch (Exception e) { 1761 RuntimeException exception = new RuntimeException("Failed to start provided temp data store: " + tempDataStore, e); 1762 LOG.error(exception.getLocalizedMessage(), e); 1763 throw exception; 1764 } 1765 } 1766 1767 public int getPersistenceThreadPriority() { 1768 return persistenceThreadPriority; 1769 } 1770 1771 public void setPersistenceThreadPriority(int persistenceThreadPriority) { 1772 this.persistenceThreadPriority = persistenceThreadPriority; 1773 } 1774 1775 /** 1776 * @return the useLocalHostBrokerName 1777 */ 1778 public boolean isUseLocalHostBrokerName() { 1779 return this.useLocalHostBrokerName; 1780 } 1781 1782 /** 1783 * @param useLocalHostBrokerName 1784 * the useLocalHostBrokerName to set 1785 */ 1786 public void setUseLocalHostBrokerName(boolean useLocalHostBrokerName) { 1787 this.useLocalHostBrokerName = useLocalHostBrokerName; 1788 if (useLocalHostBrokerName && !started.get() && brokerName == null || brokerName == DEFAULT_BROKER_NAME) { 1789 brokerName = LOCAL_HOST_NAME; 1790 } 1791 } 1792 1793 /** 1794 * Looks up and lazily creates if necessary the destination for the given 1795 * JMS name 1796 */ 1797 public Destination getDestination(ActiveMQDestination destination) throws Exception { 1798 return getBroker().addDestination(getAdminConnectionContext(), destination,false); 1799 } 1800 1801 public void removeDestination(ActiveMQDestination destination) throws Exception { 1802 getBroker().removeDestination(getAdminConnectionContext(), destination, 0); 1803 } 1804 1805 public int getProducerSystemUsagePortion() { 1806 return producerSystemUsagePortion; 1807 } 1808 1809 public void setProducerSystemUsagePortion(int producerSystemUsagePortion) { 1810 this.producerSystemUsagePortion = producerSystemUsagePortion; 1811 } 1812 1813 public int getConsumerSystemUsagePortion() { 1814 return consumerSystemUsagePortion; 1815 } 1816 1817 public void setConsumerSystemUsagePortion(int consumerSystemUsagePortion) { 1818 this.consumerSystemUsagePortion = consumerSystemUsagePortion; 1819 } 1820 1821 public boolean isSplitSystemUsageForProducersConsumers() { 1822 return splitSystemUsageForProducersConsumers; 1823 } 1824 1825 public void setSplitSystemUsageForProducersConsumers(boolean splitSystemUsageForProducersConsumers) { 1826 this.splitSystemUsageForProducersConsumers = splitSystemUsageForProducersConsumers; 1827 } 1828 1829 public boolean isMonitorConnectionSplits() { 1830 return monitorConnectionSplits; 1831 } 1832 1833 public void setMonitorConnectionSplits(boolean monitorConnectionSplits) { 1834 this.monitorConnectionSplits = monitorConnectionSplits; 1835 } 1836 1837 public int getTaskRunnerPriority() { 1838 return taskRunnerPriority; 1839 } 1840 1841 public void setTaskRunnerPriority(int taskRunnerPriority) { 1842 this.taskRunnerPriority = taskRunnerPriority; 1843 } 1844 1845 public boolean isDedicatedTaskRunner() { 1846 return dedicatedTaskRunner; 1847 } 1848 1849 public void setDedicatedTaskRunner(boolean dedicatedTaskRunner) { 1850 this.dedicatedTaskRunner = dedicatedTaskRunner; 1851 } 1852 1853 public boolean isCacheTempDestinations() { 1854 return cacheTempDestinations; 1855 } 1856 1857 public void setCacheTempDestinations(boolean cacheTempDestinations) { 1858 this.cacheTempDestinations = cacheTempDestinations; 1859 } 1860 1861 public int getTimeBeforePurgeTempDestinations() { 1862 return timeBeforePurgeTempDestinations; 1863 } 1864 1865 public void setTimeBeforePurgeTempDestinations(int timeBeforePurgeTempDestinations) { 1866 this.timeBeforePurgeTempDestinations = timeBeforePurgeTempDestinations; 1867 } 1868 1869 public boolean isUseTempMirroredQueues() { 1870 return useTempMirroredQueues; 1871 } 1872 1873 public void setUseTempMirroredQueues(boolean useTempMirroredQueues) { 1874 this.useTempMirroredQueues = useTempMirroredQueues; 1875 } 1876 1877 public synchronized JobSchedulerStore getJobSchedulerStore() { 1878 1879 // If support is off don't allow any scheduler even is user configured their own. 1880 if (!isSchedulerSupport()) { 1881 return null; 1882 } 1883 1884 // If the user configured their own we use it even if persistence is disabled since 1885 // we don't know anything about their implementation. 1886 if (jobSchedulerStore == null) { 1887 1888 if (!isPersistent()) { 1889 this.jobSchedulerStore = new InMemoryJobSchedulerStore(); 1890 configureService(jobSchedulerStore); 1891 return this.jobSchedulerStore; 1892 } 1893 1894 try { 1895 PersistenceAdapter pa = getPersistenceAdapter(); 1896 if (pa != null) { 1897 this.jobSchedulerStore = pa.createJobSchedulerStore(); 1898 jobSchedulerStore.setDirectory(getSchedulerDirectoryFile()); 1899 configureService(jobSchedulerStore); 1900 return this.jobSchedulerStore; 1901 } 1902 } catch (IOException e) { 1903 throw new RuntimeException(e); 1904 } catch (UnsupportedOperationException ex) { 1905 // It's ok if the store doesn't implement a scheduler. 1906 } catch (Exception e) { 1907 throw new RuntimeException(e); 1908 } 1909 1910 try { 1911 PersistenceAdapter pa = getPersistenceAdapter(); 1912 if (pa != null && pa instanceof JobSchedulerStore) { 1913 this.jobSchedulerStore = (JobSchedulerStore) pa; 1914 configureService(jobSchedulerStore); 1915 return this.jobSchedulerStore; 1916 } 1917 } catch (IOException e) { 1918 throw new RuntimeException(e); 1919 } 1920 1921 // Load the KahaDB store as a last resort, this only works if KahaDB is 1922 // included at runtime, otherwise this will fail. User should disable 1923 // scheduler support if this fails. 1924 try { 1925 String clazz = "org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter"; 1926 PersistenceAdapter adaptor = (PersistenceAdapter)getClass().getClassLoader().loadClass(clazz).newInstance(); 1927 jobSchedulerStore = adaptor.createJobSchedulerStore(); 1928 jobSchedulerStore.setDirectory(getSchedulerDirectoryFile()); 1929 configureService(jobSchedulerStore); 1930 LOG.info("JobScheduler using directory: {}", getSchedulerDirectoryFile()); 1931 } catch (Exception e) { 1932 throw new RuntimeException(e); 1933 } 1934 } 1935 return jobSchedulerStore; 1936 } 1937 1938 public void setJobSchedulerStore(JobSchedulerStore jobSchedulerStore) { 1939 this.jobSchedulerStore = jobSchedulerStore; 1940 configureService(jobSchedulerStore); 1941 } 1942 1943 // 1944 // Implementation methods 1945 // ------------------------------------------------------------------------- 1946 /** 1947 * Handles any lazy-creation helper properties which are added to make 1948 * things easier to configure inside environments such as Spring 1949 * 1950 * @throws Exception 1951 */ 1952 protected void processHelperProperties() throws Exception { 1953 if (transportConnectorURIs != null) { 1954 for (int i = 0; i < transportConnectorURIs.length; i++) { 1955 String uri = transportConnectorURIs[i]; 1956 addConnector(uri); 1957 } 1958 } 1959 if (networkConnectorURIs != null) { 1960 for (int i = 0; i < networkConnectorURIs.length; i++) { 1961 String uri = networkConnectorURIs[i]; 1962 addNetworkConnector(uri); 1963 } 1964 } 1965 if (jmsBridgeConnectors != null) { 1966 for (int i = 0; i < jmsBridgeConnectors.length; i++) { 1967 addJmsConnector(jmsBridgeConnectors[i]); 1968 } 1969 } 1970 } 1971 1972 /** 1973 * Check that the store usage limit is not greater than max usable 1974 * space and adjust if it is 1975 */ 1976 protected void checkStoreUsageLimits() throws IOException { 1977 final SystemUsage usage = getSystemUsage(); 1978 1979 if (getPersistenceAdapter() != null) { 1980 PersistenceAdapter adapter = getPersistenceAdapter(); 1981 checkUsageLimit(adapter.getDirectory(), usage.getStoreUsage(), usage.getStoreUsage().getPercentLimit()); 1982 1983 long maxJournalFileSize = 0; 1984 long storeLimit = usage.getStoreUsage().getLimit(); 1985 1986 if (adapter instanceof JournaledStore) { 1987 maxJournalFileSize = ((JournaledStore) adapter).getJournalMaxFileLength(); 1988 } 1989 1990 if (storeLimit > 0 && storeLimit < maxJournalFileSize) { 1991 LOG.error("Store limit is " + storeLimit / (1024 * 1024) + 1992 " mb, whilst the max journal file size for the store is: " + 1993 maxJournalFileSize / (1024 * 1024) + " mb, " + 1994 "the store will not accept any data when used."); 1995 1996 } 1997 } 1998 } 1999 2000 /** 2001 * Check that temporary usage limit is not greater than max usable 2002 * space and adjust if it is 2003 */ 2004 protected void checkTmpStoreUsageLimits() throws IOException { 2005 final SystemUsage usage = getSystemUsage(); 2006 2007 File tmpDir = getTmpDataDirectory(); 2008 2009 if (tmpDir != null) { 2010 checkUsageLimit(tmpDir, usage.getTempUsage(), usage.getTempUsage().getPercentLimit()); 2011 2012 if (isPersistent()) { 2013 long maxJournalFileSize; 2014 2015 PListStore store = usage.getTempUsage().getStore(); 2016 if (store != null && store instanceof JournaledStore) { 2017 maxJournalFileSize = ((JournaledStore) store).getJournalMaxFileLength(); 2018 } else { 2019 maxJournalFileSize = DEFAULT_MAX_FILE_LENGTH; 2020 } 2021 long storeLimit = usage.getTempUsage().getLimit(); 2022 2023 if (storeLimit > 0 && storeLimit < maxJournalFileSize) { 2024 LOG.error("Temporary Store limit is " + storeLimit / (1024 * 1024) + 2025 " mb, whilst the max journal file size for the temporary store is: " + 2026 maxJournalFileSize / (1024 * 1024) + " mb, " + 2027 "the temp store will not accept any data when used."); 2028 } 2029 } 2030 } 2031 } 2032 2033 protected void checkUsageLimit(File dir, Usage<?> storeUsage, int percentLimit) { 2034 if (dir != null) { 2035 dir = StoreUtil.findParentDirectory(dir); 2036 String storeName = storeUsage instanceof StoreUsage ? "Store" : "Temporary Store"; 2037 long storeLimit = storeUsage.getLimit(); 2038 long storeCurrent = storeUsage.getUsage(); 2039 long totalSpace = dir.getTotalSpace(); 2040 long totalUsableSpace = dir.getUsableSpace() + storeCurrent; 2041 //compute byte value of the percent limit 2042 long bytePercentLimit = totalSpace * percentLimit / 100; 2043 int oneMeg = 1024 * 1024; 2044 2045 //Check if the store limit is less than the percent Limit that was set and also 2046 //the usable space...this means we can grow the store larger 2047 //Changes in partition size (total space) as well as changes in usable space should 2048 //be detected here 2049 if (diskUsageCheckRegrowThreshold > -1 && percentLimit > 0 2050 && storeLimit < bytePercentLimit && storeLimit < totalUsableSpace){ 2051 2052 // set the limit to be bytePercentLimit or usableSpace if 2053 // usableSpace is less than the percentLimit 2054 long newLimit = bytePercentLimit > totalUsableSpace ? totalUsableSpace : bytePercentLimit; 2055 2056 //To prevent changing too often, check threshold 2057 if (newLimit - storeLimit >= diskUsageCheckRegrowThreshold) { 2058 LOG.info("Usable disk space has been increased, attempting to regrow " + storeName + " limit to " 2059 + percentLimit + "% of the partition size."); 2060 storeUsage.setLimit(newLimit); 2061 LOG.info(storeName + " limit has been increased to " + newLimit * 100 / totalSpace 2062 + "% (" + newLimit / oneMeg + " mb) of the partition size."); 2063 } 2064 2065 //check if the limit is too large for the amount of usable space 2066 } else if (storeLimit > totalUsableSpace) { 2067 if (percentLimit > 0) { 2068 LOG.warn(storeName + " limit has been set to " 2069 + percentLimit + "% (" + bytePercentLimit / oneMeg + " mb)" 2070 + " of the partition size but there is not enough usable space." 2071 + " The current store limit (which may have been adjusted by a" 2072 + " previous usage limit check) is set to (" + storeLimit / oneMeg + " mb)" 2073 + " but only " + totalUsableSpace * 100 / totalSpace + "% (" + totalUsableSpace / oneMeg + " mb)" 2074 + " is available - resetting limit"); 2075 } 2076 2077 LOG.warn(storeName + " limit is " + storeLimit / oneMeg + 2078 " mb (current store usage is " + storeCurrent / oneMeg + 2079 " mb). The data directory: " + dir.getAbsolutePath() + 2080 " only has " + totalUsableSpace / oneMeg + 2081 " mb of usable space - resetting to maximum available disk space: " + 2082 totalUsableSpace / oneMeg + " mb"); 2083 storeUsage.setLimit(totalUsableSpace); 2084 } 2085 } 2086 } 2087 2088 /** 2089 * Schedules a periodic task based on schedulePeriodForDiskLimitCheck to 2090 * update store and temporary store limits if the amount of available space 2091 * plus current store size is less than the existin configured limit 2092 */ 2093 protected void scheduleDiskUsageLimitsCheck() throws IOException { 2094 if (schedulePeriodForDiskUsageCheck > 0 && 2095 (getPersistenceAdapter() != null || getTmpDataDirectory() != null)) { 2096 Runnable diskLimitCheckTask = new Runnable() { 2097 @Override 2098 public void run() { 2099 try { 2100 checkStoreUsageLimits(); 2101 } catch (IOException e) { 2102 LOG.error("Failed to check persistent disk usage limits", e); 2103 } 2104 2105 try { 2106 checkTmpStoreUsageLimits(); 2107 } catch (IOException e) { 2108 LOG.error("Failed to check temporary store usage limits", e); 2109 } 2110 } 2111 }; 2112 scheduler.executePeriodically(diskLimitCheckTask, schedulePeriodForDiskUsageCheck); 2113 } 2114 } 2115 2116 protected void checkSystemUsageLimits() throws IOException { 2117 final SystemUsage usage = getSystemUsage(); 2118 long memLimit = usage.getMemoryUsage().getLimit(); 2119 long jvmLimit = Runtime.getRuntime().maxMemory(); 2120 2121 if (memLimit > jvmLimit) { 2122 usage.getMemoryUsage().setPercentOfJvmHeap(70); 2123 LOG.warn("Memory Usage for the Broker (" + memLimit / (1024 * 1024) + 2124 " mb) is more than the maximum available for the JVM: " + 2125 jvmLimit / (1024 * 1024) + " mb - resetting to 70% of maximum available: " + (usage.getMemoryUsage().getLimit() / (1024 * 1024)) + " mb"); 2126 } 2127 2128 //Check the persistent store and temp store limits if they exist 2129 //and schedule a periodic check to update disk limits if 2130 //schedulePeriodForDiskLimitCheck is set 2131 checkStoreUsageLimits(); 2132 checkTmpStoreUsageLimits(); 2133 scheduleDiskUsageLimitsCheck(); 2134 2135 if (getJobSchedulerStore() != null) { 2136 JobSchedulerStore scheduler = getJobSchedulerStore(); 2137 File schedulerDir = scheduler.getDirectory(); 2138 if (schedulerDir != null) { 2139 2140 String schedulerDirPath = schedulerDir.getAbsolutePath(); 2141 if (!schedulerDir.isAbsolute()) { 2142 schedulerDir = new File(schedulerDirPath); 2143 } 2144 2145 while (schedulerDir != null && !schedulerDir.isDirectory()) { 2146 schedulerDir = schedulerDir.getParentFile(); 2147 } 2148 long schedulerLimit = usage.getJobSchedulerUsage().getLimit(); 2149 long dirFreeSpace = schedulerDir.getUsableSpace(); 2150 if (schedulerLimit > dirFreeSpace) { 2151 LOG.warn("Job Scheduler Store limit is " + schedulerLimit / (1024 * 1024) + 2152 " mb, whilst the data directory: " + schedulerDir.getAbsolutePath() + 2153 " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space - resetting to " + 2154 dirFreeSpace / (1024 * 1024) + " mb."); 2155 usage.getJobSchedulerUsage().setLimit(dirFreeSpace); 2156 } 2157 } 2158 } 2159 } 2160 2161 public void stopAllConnectors(ServiceStopper stopper) { 2162 for (Iterator<NetworkConnector> iter = getNetworkConnectors().iterator(); iter.hasNext();) { 2163 NetworkConnector connector = iter.next(); 2164 unregisterNetworkConnectorMBean(connector); 2165 stopper.stop(connector); 2166 } 2167 for (Iterator<ProxyConnector> iter = getProxyConnectors().iterator(); iter.hasNext();) { 2168 ProxyConnector connector = iter.next(); 2169 stopper.stop(connector); 2170 } 2171 for (Iterator<JmsConnector> iter = jmsConnectors.iterator(); iter.hasNext();) { 2172 JmsConnector connector = iter.next(); 2173 stopper.stop(connector); 2174 } 2175 for (Iterator<TransportConnector> iter = getTransportConnectors().iterator(); iter.hasNext();) { 2176 TransportConnector connector = iter.next(); 2177 try { 2178 unregisterConnectorMBean(connector); 2179 } catch (IOException e) { 2180 } 2181 stopper.stop(connector); 2182 } 2183 } 2184 2185 protected TransportConnector registerConnectorMBean(TransportConnector connector) throws IOException { 2186 try { 2187 ObjectName objectName = createConnectorObjectName(connector); 2188 connector = connector.asManagedConnector(getManagementContext(), objectName); 2189 ConnectorViewMBean view = new ConnectorView(connector); 2190 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2191 return connector; 2192 } catch (Throwable e) { 2193 throw IOExceptionSupport.create("Transport Connector could not be registered in JMX: " + e, e); 2194 } 2195 } 2196 2197 protected void unregisterConnectorMBean(TransportConnector connector) throws IOException { 2198 if (isUseJmx()) { 2199 try { 2200 ObjectName objectName = createConnectorObjectName(connector); 2201 getManagementContext().unregisterMBean(objectName); 2202 } catch (Throwable e) { 2203 throw IOExceptionSupport.create( 2204 "Transport Connector could not be unregistered in JMX: " + e.getMessage(), e); 2205 } 2206 } 2207 } 2208 2209 protected PersistenceAdapter registerPersistenceAdapterMBean(PersistenceAdapter adaptor) throws IOException { 2210 return adaptor; 2211 } 2212 2213 protected void unregisterPersistenceAdapterMBean(PersistenceAdapter adaptor) throws IOException { 2214 if (isUseJmx()) {} 2215 } 2216 2217 private ObjectName createConnectorObjectName(TransportConnector connector) throws MalformedObjectNameException { 2218 return BrokerMBeanSupport.createConnectorName(getBrokerObjectName(), "clientConnectors", connector.getName()); 2219 } 2220 2221 public void registerNetworkConnectorMBean(NetworkConnector connector) throws IOException { 2222 NetworkConnectorViewMBean view = new NetworkConnectorView(connector); 2223 try { 2224 ObjectName objectName = createNetworkConnectorObjectName(connector); 2225 connector.setObjectName(objectName); 2226 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2227 } catch (Throwable e) { 2228 throw IOExceptionSupport.create("Network Connector could not be registered in JMX: " + e.getMessage(), e); 2229 } 2230 } 2231 2232 protected ObjectName createNetworkConnectorObjectName(NetworkConnector connector) throws MalformedObjectNameException { 2233 return BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "networkConnectors", connector.getName()); 2234 } 2235 2236 public ObjectName createDuplexNetworkConnectorObjectName(String transport) throws MalformedObjectNameException { 2237 return BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "duplexNetworkConnectors", transport); 2238 } 2239 2240 protected void unregisterNetworkConnectorMBean(NetworkConnector connector) { 2241 if (isUseJmx()) { 2242 try { 2243 ObjectName objectName = createNetworkConnectorObjectName(connector); 2244 getManagementContext().unregisterMBean(objectName); 2245 } catch (Exception e) { 2246 LOG.warn("Network Connector could not be unregistered from JMX due " + e.getMessage() + ". This exception is ignored.", e); 2247 } 2248 } 2249 } 2250 2251 protected void registerProxyConnectorMBean(ProxyConnector connector) throws IOException { 2252 ProxyConnectorView view = new ProxyConnectorView(connector); 2253 try { 2254 ObjectName objectName = BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "proxyConnectors", connector.getName()); 2255 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2256 } catch (Throwable e) { 2257 throw IOExceptionSupport.create("Broker could not be registered in JMX: " + e.getMessage(), e); 2258 } 2259 } 2260 2261 protected void registerJmsConnectorMBean(JmsConnector connector) throws IOException { 2262 JmsConnectorView view = new JmsConnectorView(connector); 2263 try { 2264 ObjectName objectName = BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "jmsConnectors", connector.getName()); 2265 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2266 } catch (Throwable e) { 2267 throw IOExceptionSupport.create("Broker could not be registered in JMX: " + e.getMessage(), e); 2268 } 2269 } 2270 2271 /** 2272 * Factory method to create a new broker 2273 * 2274 * @throws Exception 2275 */ 2276 protected Broker createBroker() throws Exception { 2277 regionBroker = createRegionBroker(); 2278 Broker broker = addInterceptors(regionBroker); 2279 // Add a filter that will stop access to the broker once stopped 2280 broker = new MutableBrokerFilter(broker) { 2281 Broker old; 2282 2283 @Override 2284 public void stop() throws Exception { 2285 old = this.next.getAndSet(new ErrorBroker("Broker has been stopped: " + this) { 2286 // Just ignore additional stop actions. 2287 @Override 2288 public void stop() throws Exception { 2289 } 2290 }); 2291 old.stop(); 2292 } 2293 2294 @Override 2295 public void start() throws Exception { 2296 if (forceStart && old != null) { 2297 this.next.set(old); 2298 } 2299 getNext().start(); 2300 } 2301 }; 2302 return broker; 2303 } 2304 2305 /** 2306 * Factory method to create the core region broker onto which interceptors 2307 * are added 2308 * 2309 * @throws Exception 2310 */ 2311 protected Broker createRegionBroker() throws Exception { 2312 if (destinationInterceptors == null) { 2313 destinationInterceptors = createDefaultDestinationInterceptor(); 2314 } 2315 configureServices(destinationInterceptors); 2316 DestinationInterceptor destinationInterceptor = new CompositeDestinationInterceptor(destinationInterceptors); 2317 if (destinationFactory == null) { 2318 destinationFactory = new DestinationFactoryImpl(this, getTaskRunnerFactory(), getPersistenceAdapter()); 2319 } 2320 return createRegionBroker(destinationInterceptor); 2321 } 2322 2323 protected Broker createRegionBroker(DestinationInterceptor destinationInterceptor) throws IOException { 2324 RegionBroker regionBroker; 2325 if (isUseJmx()) { 2326 try { 2327 regionBroker = new ManagedRegionBroker(this, getManagementContext(), getBrokerObjectName(), 2328 getTaskRunnerFactory(), getConsumerSystemUsage(), destinationFactory, destinationInterceptor,getScheduler(),getExecutor()); 2329 } catch(MalformedObjectNameException me){ 2330 LOG.warn("Cannot create ManagedRegionBroker due " + me.getMessage(), me); 2331 throw new IOException(me); 2332 } 2333 } else { 2334 regionBroker = new RegionBroker(this, getTaskRunnerFactory(), getConsumerSystemUsage(), destinationFactory, 2335 destinationInterceptor,getScheduler(),getExecutor()); 2336 } 2337 destinationFactory.setRegionBroker(regionBroker); 2338 regionBroker.setKeepDurableSubsActive(keepDurableSubsActive); 2339 regionBroker.setBrokerName(getBrokerName()); 2340 regionBroker.getDestinationStatistics().setEnabled(enableStatistics); 2341 regionBroker.setAllowTempAutoCreationOnSend(isAllowTempAutoCreationOnSend()); 2342 if (brokerId != null) { 2343 regionBroker.setBrokerId(brokerId); 2344 } 2345 return regionBroker; 2346 } 2347 2348 /** 2349 * Create the default destination interceptor 2350 */ 2351 protected DestinationInterceptor[] createDefaultDestinationInterceptor() { 2352 List<DestinationInterceptor> answer = new ArrayList<DestinationInterceptor>(); 2353 if (isUseVirtualTopics()) { 2354 VirtualDestinationInterceptor interceptor = new VirtualDestinationInterceptor(); 2355 VirtualTopic virtualTopic = new VirtualTopic(); 2356 virtualTopic.setName("VirtualTopic.>"); 2357 VirtualDestination[] virtualDestinations = { virtualTopic }; 2358 interceptor.setVirtualDestinations(virtualDestinations); 2359 answer.add(interceptor); 2360 } 2361 if (isUseMirroredQueues()) { 2362 MirroredQueue interceptor = new MirroredQueue(); 2363 answer.add(interceptor); 2364 } 2365 DestinationInterceptor[] array = new DestinationInterceptor[answer.size()]; 2366 answer.toArray(array); 2367 return array; 2368 } 2369 2370 /** 2371 * Strategy method to add interceptors to the broker 2372 * 2373 * @throws IOException 2374 */ 2375 protected Broker addInterceptors(Broker broker) throws Exception { 2376 if (isSchedulerSupport()) { 2377 SchedulerBroker sb = new SchedulerBroker(this, broker, getJobSchedulerStore()); 2378 if (isUseJmx()) { 2379 JobSchedulerViewMBean view = new JobSchedulerView(sb.getJobScheduler()); 2380 try { 2381 ObjectName objectName = BrokerMBeanSupport.createJobSchedulerServiceName(getBrokerObjectName()); 2382 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2383 this.adminView.setJMSJobScheduler(objectName); 2384 } catch (Throwable e) { 2385 throw IOExceptionSupport.create("JobScheduler could not be registered in JMX: " 2386 + e.getMessage(), e); 2387 } 2388 } 2389 broker = sb; 2390 } 2391 if (isUseJmx()) { 2392 HealthViewMBean statusView = new HealthView((ManagedRegionBroker)getRegionBroker()); 2393 try { 2394 ObjectName objectName = BrokerMBeanSupport.createHealthServiceName(getBrokerObjectName()); 2395 AnnotatedMBean.registerMBean(getManagementContext(), statusView, objectName); 2396 } catch (Throwable e) { 2397 throw IOExceptionSupport.create("Status MBean could not be registered in JMX: " 2398 + e.getMessage(), e); 2399 } 2400 } 2401 if (isAdvisorySupport()) { 2402 broker = new AdvisoryBroker(broker); 2403 } 2404 broker = new CompositeDestinationBroker(broker); 2405 broker = new TransactionBroker(broker, getPersistenceAdapter().createTransactionStore()); 2406 if (isPopulateJMSXUserID()) { 2407 UserIDBroker userIDBroker = new UserIDBroker(broker); 2408 userIDBroker.setUseAuthenticatePrincipal(isUseAuthenticatedPrincipalForJMSXUserID()); 2409 broker = userIDBroker; 2410 } 2411 if (isMonitorConnectionSplits()) { 2412 broker = new ConnectionSplitBroker(broker); 2413 } 2414 if (plugins != null) { 2415 for (int i = 0; i < plugins.length; i++) { 2416 BrokerPlugin plugin = plugins[i]; 2417 broker = plugin.installPlugin(broker); 2418 } 2419 } 2420 return broker; 2421 } 2422 2423 protected PersistenceAdapter createPersistenceAdapter() throws IOException { 2424 if (isPersistent()) { 2425 PersistenceAdapterFactory fac = getPersistenceFactory(); 2426 if (fac != null) { 2427 return fac.createPersistenceAdapter(); 2428 } else { 2429 try { 2430 String clazz = "org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter"; 2431 PersistenceAdapter adaptor = (PersistenceAdapter)getClass().getClassLoader().loadClass(clazz).newInstance(); 2432 File dir = new File(getBrokerDataDirectory(),"KahaDB"); 2433 adaptor.setDirectory(dir); 2434 return adaptor; 2435 } catch (Throwable e) { 2436 throw IOExceptionSupport.create(e); 2437 } 2438 } 2439 } else { 2440 return new MemoryPersistenceAdapter(); 2441 } 2442 } 2443 2444 protected ObjectName createBrokerObjectName() throws MalformedObjectNameException { 2445 return BrokerMBeanSupport.createBrokerObjectName(getManagementContext().getJmxDomainName(), getBrokerName()); 2446 } 2447 2448 protected TransportConnector createTransportConnector(URI brokerURI) throws Exception { 2449 TransportServer transport = TransportFactorySupport.bind(this, brokerURI); 2450 return new TransportConnector(transport); 2451 } 2452 2453 /** 2454 * Extracts the port from the options 2455 */ 2456 protected Object getPort(Map<?,?> options) { 2457 Object port = options.get("port"); 2458 if (port == null) { 2459 port = DEFAULT_PORT; 2460 LOG.warn("No port specified so defaulting to: {}", port); 2461 } 2462 return port; 2463 } 2464 2465 protected void addShutdownHook() { 2466 if (useShutdownHook) { 2467 shutdownHook = new Thread("ActiveMQ ShutdownHook") { 2468 @Override 2469 public void run() { 2470 containerShutdown(); 2471 } 2472 }; 2473 Runtime.getRuntime().addShutdownHook(shutdownHook); 2474 } 2475 } 2476 2477 protected void removeShutdownHook() { 2478 if (shutdownHook != null) { 2479 try { 2480 Runtime.getRuntime().removeShutdownHook(shutdownHook); 2481 } catch (Exception e) { 2482 LOG.debug("Caught exception, must be shutting down. This exception is ignored.", e); 2483 } 2484 } 2485 } 2486 2487 /** 2488 * Sets hooks to be executed when broker shut down 2489 * 2490 * @org.apache.xbean.Property 2491 */ 2492 public void setShutdownHooks(List<Runnable> hooks) throws Exception { 2493 for (Runnable hook : hooks) { 2494 addShutdownHook(hook); 2495 } 2496 } 2497 2498 /** 2499 * Causes a clean shutdown of the container when the VM is being shut down 2500 */ 2501 protected void containerShutdown() { 2502 try { 2503 stop(); 2504 } catch (IOException e) { 2505 Throwable linkedException = e.getCause(); 2506 if (linkedException != null) { 2507 logError("Failed to shut down: " + e + ". Reason: " + linkedException, linkedException); 2508 } else { 2509 logError("Failed to shut down: " + e, e); 2510 } 2511 if (!useLoggingForShutdownErrors) { 2512 e.printStackTrace(System.err); 2513 } 2514 } catch (Exception e) { 2515 logError("Failed to shut down: " + e, e); 2516 } 2517 } 2518 2519 protected void logError(String message, Throwable e) { 2520 if (useLoggingForShutdownErrors) { 2521 LOG.error("Failed to shut down: " + e); 2522 } else { 2523 System.err.println("Failed to shut down: " + e); 2524 } 2525 } 2526 2527 /** 2528 * Starts any configured destinations on startup 2529 */ 2530 protected void startDestinations() throws Exception { 2531 if (destinations != null) { 2532 ConnectionContext adminConnectionContext = getAdminConnectionContext(); 2533 for (int i = 0; i < destinations.length; i++) { 2534 ActiveMQDestination destination = destinations[i]; 2535 getBroker().addDestination(adminConnectionContext, destination,true); 2536 } 2537 } 2538 if (isUseVirtualTopics()) { 2539 startVirtualConsumerDestinations(); 2540 } 2541 } 2542 2543 /** 2544 * Returns the broker's administration connection context used for 2545 * configuring the broker at startup 2546 */ 2547 public ConnectionContext getAdminConnectionContext() throws Exception { 2548 return BrokerSupport.getConnectionContext(getBroker()); 2549 } 2550 2551 protected void startManagementContext() throws Exception { 2552 getManagementContext().setBrokerName(brokerName); 2553 getManagementContext().start(); 2554 adminView = new BrokerView(this, null); 2555 ObjectName objectName = getBrokerObjectName(); 2556 AnnotatedMBean.registerMBean(getManagementContext(), adminView, objectName); 2557 } 2558 2559 /** 2560 * Start all transport and network connections, proxies and bridges 2561 * 2562 * @throws Exception 2563 */ 2564 public void startAllConnectors() throws Exception { 2565 Set<ActiveMQDestination> durableDestinations = getBroker().getDurableDestinations(); 2566 List<TransportConnector> al = new ArrayList<TransportConnector>(); 2567 for (Iterator<TransportConnector> iter = getTransportConnectors().iterator(); iter.hasNext();) { 2568 TransportConnector connector = iter.next(); 2569 al.add(startTransportConnector(connector)); 2570 } 2571 if (al.size() > 0) { 2572 // let's clear the transportConnectors list and replace it with 2573 // the started transportConnector instances 2574 this.transportConnectors.clear(); 2575 setTransportConnectors(al); 2576 } 2577 this.slave = false; 2578 URI uri = getVmConnectorURI(); 2579 Map<String, String> map = new HashMap<String, String>(URISupport.parseParameters(uri)); 2580 map.put("async", "false"); 2581 uri = URISupport.createURIWithQuery(uri, URISupport.createQueryString(map)); 2582 2583 if (!stopped.get()) { 2584 ThreadPoolExecutor networkConnectorStartExecutor = null; 2585 if (isNetworkConnectorStartAsync()) { 2586 // spin up as many threads as needed 2587 networkConnectorStartExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 2588 10, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), 2589 new ThreadFactory() { 2590 int count=0; 2591 @Override 2592 public Thread newThread(Runnable runnable) { 2593 Thread thread = new Thread(runnable, "NetworkConnector Start Thread-" +(count++)); 2594 thread.setDaemon(true); 2595 return thread; 2596 } 2597 }); 2598 } 2599 2600 for (Iterator<NetworkConnector> iter = getNetworkConnectors().iterator(); iter.hasNext();) { 2601 final NetworkConnector connector = iter.next(); 2602 connector.setLocalUri(uri); 2603 connector.setBrokerName(getBrokerName()); 2604 connector.setDurableDestinations(durableDestinations); 2605 if (getDefaultSocketURIString() != null) { 2606 connector.setBrokerURL(getDefaultSocketURIString()); 2607 } 2608 if (networkConnectorStartExecutor != null) { 2609 networkConnectorStartExecutor.execute(new Runnable() { 2610 @Override 2611 public void run() { 2612 try { 2613 LOG.info("Async start of {}", connector); 2614 connector.start(); 2615 } catch(Exception e) { 2616 LOG.error("Async start of network connector: {} failed", connector, e); 2617 } 2618 } 2619 }); 2620 } else { 2621 connector.start(); 2622 } 2623 } 2624 if (networkConnectorStartExecutor != null) { 2625 // executor done when enqueued tasks are complete 2626 ThreadPoolUtils.shutdown(networkConnectorStartExecutor); 2627 } 2628 2629 for (Iterator<ProxyConnector> iter = getProxyConnectors().iterator(); iter.hasNext();) { 2630 ProxyConnector connector = iter.next(); 2631 connector.start(); 2632 } 2633 for (Iterator<JmsConnector> iter = jmsConnectors.iterator(); iter.hasNext();) { 2634 JmsConnector connector = iter.next(); 2635 connector.start(); 2636 } 2637 for (Service service : services) { 2638 configureService(service); 2639 service.start(); 2640 } 2641 } 2642 } 2643 2644 public TransportConnector startTransportConnector(TransportConnector connector) throws Exception { 2645 connector.setBrokerService(this); 2646 connector.setTaskRunnerFactory(getTaskRunnerFactory()); 2647 MessageAuthorizationPolicy policy = getMessageAuthorizationPolicy(); 2648 if (policy != null) { 2649 connector.setMessageAuthorizationPolicy(policy); 2650 } 2651 if (isUseJmx()) { 2652 connector = registerConnectorMBean(connector); 2653 } 2654 connector.getStatistics().setEnabled(enableStatistics); 2655 connector.start(); 2656 return connector; 2657 } 2658 2659 /** 2660 * Perform any custom dependency injection 2661 */ 2662 protected void configureServices(Object[] services) { 2663 for (Object service : services) { 2664 configureService(service); 2665 } 2666 } 2667 2668 /** 2669 * Perform any custom dependency injection 2670 */ 2671 protected void configureService(Object service) { 2672 if (service instanceof BrokerServiceAware) { 2673 BrokerServiceAware serviceAware = (BrokerServiceAware) service; 2674 serviceAware.setBrokerService(this); 2675 } 2676 } 2677 2678 public void handleIOException(IOException exception) { 2679 if (ioExceptionHandler != null) { 2680 ioExceptionHandler.handle(exception); 2681 } else { 2682 LOG.info("No IOExceptionHandler registered, ignoring IO exception", exception); 2683 } 2684 } 2685 2686 protected void startVirtualConsumerDestinations() throws Exception { 2687 ConnectionContext adminConnectionContext = getAdminConnectionContext(); 2688 Set<ActiveMQDestination> destinations = destinationFactory.getDestinations(); 2689 DestinationFilter filter = getVirtualTopicConsumerDestinationFilter(); 2690 if (!destinations.isEmpty()) { 2691 for (ActiveMQDestination destination : destinations) { 2692 if (filter.matches(destination) == true) { 2693 broker.addDestination(adminConnectionContext, destination, false); 2694 } 2695 } 2696 } 2697 } 2698 2699 private DestinationFilter getVirtualTopicConsumerDestinationFilter() { 2700 // created at startup, so no sync needed 2701 if (virtualConsumerDestinationFilter == null) { 2702 Set <ActiveMQQueue> consumerDestinations = new HashSet<ActiveMQQueue>(); 2703 if (destinationInterceptors != null) { 2704 for (DestinationInterceptor interceptor : destinationInterceptors) { 2705 if (interceptor instanceof VirtualDestinationInterceptor) { 2706 VirtualDestinationInterceptor virtualDestinationInterceptor = (VirtualDestinationInterceptor) interceptor; 2707 for (VirtualDestination virtualDestination: virtualDestinationInterceptor.getVirtualDestinations()) { 2708 if (virtualDestination instanceof VirtualTopic) { 2709 consumerDestinations.add(new ActiveMQQueue(((VirtualTopic) virtualDestination).getPrefix() + DestinationFilter.ANY_DESCENDENT)); 2710 } 2711 if (isUseVirtualDestSubs()) { 2712 try { 2713 broker.virtualDestinationAdded(getAdminConnectionContext(), virtualDestination); 2714 LOG.debug("Adding virtual destination: {}", virtualDestination); 2715 } catch (Exception e) { 2716 LOG.warn("Could not fire virtual destination consumer advisory", e); 2717 } 2718 } 2719 } 2720 } 2721 } 2722 } 2723 ActiveMQQueue filter = new ActiveMQQueue(); 2724 filter.setCompositeDestinations(consumerDestinations.toArray(new ActiveMQDestination[]{})); 2725 virtualConsumerDestinationFilter = DestinationFilter.parseFilter(filter); 2726 } 2727 return virtualConsumerDestinationFilter; 2728 } 2729 2730 protected synchronized ThreadPoolExecutor getExecutor() { 2731 if (this.executor == null) { 2732 this.executor = new ThreadPoolExecutor(1, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() { 2733 2734 private long i = 0; 2735 2736 @Override 2737 public Thread newThread(Runnable runnable) { 2738 this.i++; 2739 Thread thread = new Thread(runnable, "ActiveMQ BrokerService.worker." + this.i); 2740 thread.setDaemon(true); 2741 thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 2742 @Override 2743 public void uncaughtException(final Thread t, final Throwable e) { 2744 LOG.error("Error in thread '{}'", t.getName(), e); 2745 } 2746 }); 2747 return thread; 2748 } 2749 }, new RejectedExecutionHandler() { 2750 @Override 2751 public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { 2752 try { 2753 executor.getQueue().offer(r, 60, TimeUnit.SECONDS); 2754 } catch (InterruptedException e) { 2755 throw new RejectedExecutionException("Interrupted waiting for BrokerService.worker"); 2756 } 2757 2758 throw new RejectedExecutionException("Timed Out while attempting to enqueue Task."); 2759 } 2760 }); 2761 } 2762 return this.executor; 2763 } 2764 2765 public synchronized Scheduler getScheduler() { 2766 if (this.scheduler==null) { 2767 this.scheduler = new Scheduler("ActiveMQ Broker["+getBrokerName()+"] Scheduler"); 2768 try { 2769 this.scheduler.start(); 2770 } catch (Exception e) { 2771 LOG.error("Failed to start Scheduler", e); 2772 } 2773 } 2774 return this.scheduler; 2775 } 2776 2777 public Broker getRegionBroker() { 2778 return regionBroker; 2779 } 2780 2781 public void setRegionBroker(Broker regionBroker) { 2782 this.regionBroker = regionBroker; 2783 } 2784 2785 public void addShutdownHook(Runnable hook) { 2786 synchronized (shutdownHooks) { 2787 shutdownHooks.add(hook); 2788 } 2789 } 2790 2791 public void removeShutdownHook(Runnable hook) { 2792 synchronized (shutdownHooks) { 2793 shutdownHooks.remove(hook); 2794 } 2795 } 2796 2797 public boolean isSystemExitOnShutdown() { 2798 return systemExitOnShutdown; 2799 } 2800 2801 /** 2802 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2803 */ 2804 public void setSystemExitOnShutdown(boolean systemExitOnShutdown) { 2805 this.systemExitOnShutdown = systemExitOnShutdown; 2806 } 2807 2808 public int getSystemExitOnShutdownExitCode() { 2809 return systemExitOnShutdownExitCode; 2810 } 2811 2812 public void setSystemExitOnShutdownExitCode(int systemExitOnShutdownExitCode) { 2813 this.systemExitOnShutdownExitCode = systemExitOnShutdownExitCode; 2814 } 2815 2816 public SslContext getSslContext() { 2817 return sslContext; 2818 } 2819 2820 public void setSslContext(SslContext sslContext) { 2821 this.sslContext = sslContext; 2822 } 2823 2824 public boolean isShutdownOnSlaveFailure() { 2825 return shutdownOnSlaveFailure; 2826 } 2827 2828 /** 2829 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2830 */ 2831 public void setShutdownOnSlaveFailure(boolean shutdownOnSlaveFailure) { 2832 this.shutdownOnSlaveFailure = shutdownOnSlaveFailure; 2833 } 2834 2835 public boolean isWaitForSlave() { 2836 return waitForSlave; 2837 } 2838 2839 /** 2840 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2841 */ 2842 public void setWaitForSlave(boolean waitForSlave) { 2843 this.waitForSlave = waitForSlave; 2844 } 2845 2846 public long getWaitForSlaveTimeout() { 2847 return this.waitForSlaveTimeout; 2848 } 2849 2850 public void setWaitForSlaveTimeout(long waitForSlaveTimeout) { 2851 this.waitForSlaveTimeout = waitForSlaveTimeout; 2852 } 2853 2854 /** 2855 * Get the passiveSlave 2856 * @return the passiveSlave 2857 */ 2858 public boolean isPassiveSlave() { 2859 return this.passiveSlave; 2860 } 2861 2862 /** 2863 * Set the passiveSlave 2864 * @param passiveSlave the passiveSlave to set 2865 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2866 */ 2867 public void setPassiveSlave(boolean passiveSlave) { 2868 this.passiveSlave = passiveSlave; 2869 } 2870 2871 /** 2872 * override the Default IOException handler, called when persistence adapter 2873 * has experiences File or JDBC I/O Exceptions 2874 * 2875 * @param ioExceptionHandler 2876 */ 2877 public void setIoExceptionHandler(IOExceptionHandler ioExceptionHandler) { 2878 configureService(ioExceptionHandler); 2879 this.ioExceptionHandler = ioExceptionHandler; 2880 } 2881 2882 public IOExceptionHandler getIoExceptionHandler() { 2883 return ioExceptionHandler; 2884 } 2885 2886 /** 2887 * @return the schedulerSupport 2888 */ 2889 public boolean isSchedulerSupport() { 2890 return this.schedulerSupport; 2891 } 2892 2893 /** 2894 * @param schedulerSupport the schedulerSupport to set 2895 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2896 */ 2897 public void setSchedulerSupport(boolean schedulerSupport) { 2898 this.schedulerSupport = schedulerSupport; 2899 } 2900 2901 /** 2902 * @return the schedulerDirectory 2903 */ 2904 public File getSchedulerDirectoryFile() { 2905 if (this.schedulerDirectoryFile == null) { 2906 this.schedulerDirectoryFile = new File(getBrokerDataDirectory(), "scheduler"); 2907 } 2908 return schedulerDirectoryFile; 2909 } 2910 2911 /** 2912 * @param schedulerDirectory the schedulerDirectory to set 2913 */ 2914 public void setSchedulerDirectoryFile(File schedulerDirectory) { 2915 this.schedulerDirectoryFile = schedulerDirectory; 2916 } 2917 2918 public void setSchedulerDirectory(String schedulerDirectory) { 2919 setSchedulerDirectoryFile(new File(schedulerDirectory)); 2920 } 2921 2922 public int getSchedulePeriodForDestinationPurge() { 2923 return this.schedulePeriodForDestinationPurge; 2924 } 2925 2926 public void setSchedulePeriodForDestinationPurge(int schedulePeriodForDestinationPurge) { 2927 this.schedulePeriodForDestinationPurge = schedulePeriodForDestinationPurge; 2928 } 2929 2930 /** 2931 * @param schedulePeriodForDiskUsageCheck 2932 */ 2933 public void setSchedulePeriodForDiskUsageCheck( 2934 int schedulePeriodForDiskUsageCheck) { 2935 this.schedulePeriodForDiskUsageCheck = schedulePeriodForDiskUsageCheck; 2936 } 2937 2938 public int getDiskUsageCheckRegrowThreshold() { 2939 return diskUsageCheckRegrowThreshold; 2940 } 2941 2942 /** 2943 * @param diskUsageCheckRegrowThreshold 2944 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.MemoryPropertyEditor" 2945 */ 2946 public void setDiskUsageCheckRegrowThreshold(int diskUsageCheckRegrowThreshold) { 2947 this.diskUsageCheckRegrowThreshold = diskUsageCheckRegrowThreshold; 2948 } 2949 2950 public int getMaxPurgedDestinationsPerSweep() { 2951 return this.maxPurgedDestinationsPerSweep; 2952 } 2953 2954 public void setMaxPurgedDestinationsPerSweep(int maxPurgedDestinationsPerSweep) { 2955 this.maxPurgedDestinationsPerSweep = maxPurgedDestinationsPerSweep; 2956 } 2957 2958 public BrokerContext getBrokerContext() { 2959 return brokerContext; 2960 } 2961 2962 public void setBrokerContext(BrokerContext brokerContext) { 2963 this.brokerContext = brokerContext; 2964 } 2965 2966 public void setBrokerId(String brokerId) { 2967 this.brokerId = new BrokerId(brokerId); 2968 } 2969 2970 public boolean isUseAuthenticatedPrincipalForJMSXUserID() { 2971 return useAuthenticatedPrincipalForJMSXUserID; 2972 } 2973 2974 public void setUseAuthenticatedPrincipalForJMSXUserID(boolean useAuthenticatedPrincipalForJMSXUserID) { 2975 this.useAuthenticatedPrincipalForJMSXUserID = useAuthenticatedPrincipalForJMSXUserID; 2976 } 2977 2978 /** 2979 * Should MBeans that support showing the Authenticated User Name information have this 2980 * value filled in or not. 2981 * 2982 * @return true if user names should be exposed in MBeans 2983 */ 2984 public boolean isPopulateUserNameInMBeans() { 2985 return this.populateUserNameInMBeans; 2986 } 2987 2988 /** 2989 * Sets whether Authenticated User Name information is shown in MBeans that support this field. 2990 * @param value if MBeans should expose user name information. 2991 */ 2992 public void setPopulateUserNameInMBeans(boolean value) { 2993 this.populateUserNameInMBeans = value; 2994 } 2995 2996 /** 2997 * Gets the time in Milliseconds that an invocation of an MBean method will wait before 2998 * failing. The default value is to wait forever (zero). 2999 * 3000 * @return timeout in milliseconds before MBean calls fail, (default is 0 or no timeout). 3001 */ 3002 public long getMbeanInvocationTimeout() { 3003 return mbeanInvocationTimeout; 3004 } 3005 3006 /** 3007 * Gets the time in Milliseconds that an invocation of an MBean method will wait before 3008 * failing. The default value is to wait forever (zero). 3009 * 3010 * @param mbeanInvocationTimeout 3011 * timeout in milliseconds before MBean calls fail, (default is 0 or no timeout). 3012 */ 3013 public void setMbeanInvocationTimeout(long mbeanInvocationTimeout) { 3014 this.mbeanInvocationTimeout = mbeanInvocationTimeout; 3015 } 3016 3017 public boolean isNetworkConnectorStartAsync() { 3018 return networkConnectorStartAsync; 3019 } 3020 3021 public void setNetworkConnectorStartAsync(boolean networkConnectorStartAsync) { 3022 this.networkConnectorStartAsync = networkConnectorStartAsync; 3023 } 3024 3025 public boolean isAllowTempAutoCreationOnSend() { 3026 return allowTempAutoCreationOnSend; 3027 } 3028 3029 /** 3030 * enable if temp destinations need to be propagated through a network when 3031 * advisorySupport==false. This is used in conjunction with the policy 3032 * gcInactiveDestinations for matching temps so they can get removed 3033 * when inactive 3034 * 3035 * @param allowTempAutoCreationOnSend 3036 */ 3037 public void setAllowTempAutoCreationOnSend(boolean allowTempAutoCreationOnSend) { 3038 this.allowTempAutoCreationOnSend = allowTempAutoCreationOnSend; 3039 } 3040 3041 public long getOfflineDurableSubscriberTimeout() { 3042 return offlineDurableSubscriberTimeout; 3043 } 3044 3045 public void setOfflineDurableSubscriberTimeout(long offlineDurableSubscriberTimeout) { 3046 this.offlineDurableSubscriberTimeout = offlineDurableSubscriberTimeout; 3047 } 3048 3049 public long getOfflineDurableSubscriberTaskSchedule() { 3050 return offlineDurableSubscriberTaskSchedule; 3051 } 3052 3053 public void setOfflineDurableSubscriberTaskSchedule(long offlineDurableSubscriberTaskSchedule) { 3054 this.offlineDurableSubscriberTaskSchedule = offlineDurableSubscriberTaskSchedule; 3055 } 3056 3057 public boolean shouldRecordVirtualDestination(ActiveMQDestination destination) { 3058 return isUseVirtualTopics() && destination.isQueue() && 3059 getVirtualTopicConsumerDestinationFilter().matches(destination); 3060 } 3061 3062 public Throwable getStartException() { 3063 return startException; 3064 } 3065 3066 public boolean isStartAsync() { 3067 return startAsync; 3068 } 3069 3070 public void setStartAsync(boolean startAsync) { 3071 this.startAsync = startAsync; 3072 } 3073 3074 public boolean isSlave() { 3075 return this.slave; 3076 } 3077 3078 public boolean isStopping() { 3079 return this.stopping.get(); 3080 } 3081 3082 /** 3083 * @return true if the broker allowed to restart on shutdown. 3084 */ 3085 public boolean isRestartAllowed() { 3086 return restartAllowed; 3087 } 3088 3089 /** 3090 * Sets if the broker allowed to restart on shutdown. 3091 */ 3092 public void setRestartAllowed(boolean restartAllowed) { 3093 this.restartAllowed = restartAllowed; 3094 } 3095 3096 /** 3097 * A lifecycle manager of the BrokerService should 3098 * inspect this property after a broker shutdown has occurred 3099 * to find out if the broker needs to be re-created and started 3100 * again. 3101 * 3102 * @return true if the broker wants to be restarted after it shuts down. 3103 */ 3104 public boolean isRestartRequested() { 3105 return restartRequested; 3106 } 3107 3108 public void requestRestart() { 3109 this.restartRequested = true; 3110 } 3111 3112 public int getStoreOpenWireVersion() { 3113 return storeOpenWireVersion; 3114 } 3115 3116 public void setStoreOpenWireVersion(int storeOpenWireVersion) { 3117 this.storeOpenWireVersion = storeOpenWireVersion; 3118 } 3119 3120 /** 3121 * @return the current number of connections on this Broker. 3122 */ 3123 public int getCurrentConnections() { 3124 return this.currentConnections.get(); 3125 } 3126 3127 /** 3128 * @return the total number of connections this broker has handled since startup. 3129 */ 3130 public long getTotalConnections() { 3131 return this.totalConnections.get(); 3132 } 3133 3134 public void incrementCurrentConnections() { 3135 this.currentConnections.incrementAndGet(); 3136 } 3137 3138 public void decrementCurrentConnections() { 3139 this.currentConnections.decrementAndGet(); 3140 } 3141 3142 public void incrementTotalConnections() { 3143 this.totalConnections.incrementAndGet(); 3144 } 3145 3146 public boolean isRejectDurableConsumers() { 3147 return rejectDurableConsumers; 3148 } 3149 3150 public void setRejectDurableConsumers(boolean rejectDurableConsumers) { 3151 this.rejectDurableConsumers = rejectDurableConsumers; 3152 } 3153 3154 public boolean isUseVirtualDestSubs() { 3155 return useVirtualDestSubs; 3156 } 3157 3158 public void setUseVirtualDestSubs( 3159 boolean useVirtualDestSubs) { 3160 this.useVirtualDestSubs = useVirtualDestSubs; 3161 } 3162 3163 public boolean isUseVirtualDestSubsOnCreation() { 3164 return useVirtualDestSubsOnCreation; 3165 } 3166 3167 public void setUseVirtualDestSubsOnCreation( 3168 boolean useVirtualDestSubsOnCreation) { 3169 this.useVirtualDestSubsOnCreation = useVirtualDestSubsOnCreation; 3170 } 3171}