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