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