|
| 1 | +package com.hivemq; |
| 2 | + |
| 3 | +import com.codahale.metrics.MetricRegistry; |
| 4 | +import com.google.common.base.Preconditions; |
| 5 | +import com.hivemq.api.resources.GenericAPIHolder; |
| 6 | +import com.hivemq.bootstrap.HiveMQExceptionHandlerBootstrap; |
| 7 | +import com.hivemq.bootstrap.LoggingBootstrap; |
| 8 | +import com.hivemq.bootstrap.ioc.DaggerInjector; |
| 9 | +import com.hivemq.bootstrap.ioc.Injector; |
| 10 | +import com.hivemq.bootstrap.ioc.Persistences; |
| 11 | +import com.hivemq.bootstrap.services.CompleteBootstrapService; |
| 12 | +import com.hivemq.bootstrap.services.CompleteBootstrapServiceImpl; |
| 13 | +import com.hivemq.bootstrap.services.GeneralBootstrapServiceImpl; |
| 14 | +import com.hivemq.bootstrap.services.PersistenceBootstrapService; |
| 15 | +import com.hivemq.bootstrap.services.PersistenceBootstrapServiceImpl; |
| 16 | +import com.hivemq.common.shutdown.ShutdownHooks; |
| 17 | +import com.hivemq.configuration.ConfigurationBootstrap; |
| 18 | +import com.hivemq.configuration.info.SystemInformation; |
| 19 | +import com.hivemq.configuration.service.ConfigurationService; |
| 20 | +import com.hivemq.edge.HiveMQCapabilityService; |
| 21 | +import com.hivemq.edge.impl.capability.CapabilityServiceImpl; |
| 22 | +import com.hivemq.edge.modules.ModuleLoader; |
| 23 | +import com.hivemq.exceptions.HiveMQEdgeStartupException; |
| 24 | +import com.hivemq.extension.sdk.api.annotations.NotNull; |
| 25 | +import com.hivemq.extension.sdk.api.annotations.Nullable; |
| 26 | +import com.hivemq.extensions.core.CommercialModuleLoaderDiscovery; |
| 27 | +import com.hivemq.extensions.core.HandlerService; |
| 28 | +import com.hivemq.extensions.core.PersistencesService; |
| 29 | +import com.hivemq.extensions.core.RestComponentsService; |
| 30 | +import com.hivemq.extensions.core.RestComponentsServiceImpl; |
| 31 | +import com.hivemq.metrics.MetricRegistryLogger; |
| 32 | +import com.hivemq.persistence.PersistenceStartup; |
| 33 | +import com.hivemq.persistence.connection.ConnectionPersistence; |
| 34 | +import com.hivemq.persistence.connection.ConnectionPersistenceImpl; |
| 35 | +import org.apache.commons.io.FileUtils; |
| 36 | +import org.slf4j.Logger; |
| 37 | +import org.slf4j.LoggerFactory; |
| 38 | + |
| 39 | +import java.io.File; |
| 40 | +import java.io.IOException; |
| 41 | +import java.util.Objects; |
| 42 | + |
| 43 | +public class HiveMQEdgeBootstrap { |
| 44 | + |
| 45 | + private static final @NotNull Logger log = LoggerFactory.getLogger(HiveMQEdgeBootstrap.class); |
| 46 | + |
| 47 | + private final @NotNull MetricRegistry metricRegistry; |
| 48 | + private final @NotNull SystemInformation systemInformation; |
| 49 | + private final @NotNull ModuleLoader moduleLoader; |
| 50 | + private @Nullable ConfigurationService configService; |
| 51 | + |
| 52 | + private final @NotNull PersistenceStartup persistenceStartup = new PersistenceStartup(); |
| 53 | + private final @NotNull HandlerService handlerService = new HandlerService(); |
| 54 | + private final @NotNull GenericAPIHolder genericAPIHolder = new GenericAPIHolder(); |
| 55 | + private final @NotNull ShutdownHooks shutdownHooks = new ShutdownHooks(); |
| 56 | + private final @NotNull HiveMQCapabilityService capabilityService = new CapabilityServiceImpl(); |
| 57 | + private final @NotNull ConnectionPersistence connectionPersistence = new ConnectionPersistenceImpl(); |
| 58 | + private final @NotNull PersistencesService persistencesService = new PersistencesService(persistenceStartup); |
| 59 | + private final @NotNull RestComponentsService restComponentsService = |
| 60 | + new RestComponentsServiceImpl(genericAPIHolder); |
| 61 | + private @Nullable CommercialModuleLoaderDiscovery commercialModuleLoaderDiscovery; |
| 62 | + private @Nullable GeneralBootstrapServiceImpl generalBootstrapService; |
| 63 | + private @Nullable PersistenceBootstrapService persistenceBootstrapService; |
| 64 | + private @Nullable Injector injector; |
| 65 | + |
| 66 | + public HiveMQEdgeBootstrap( |
| 67 | + final @NotNull MetricRegistry metricRegistry, |
| 68 | + final @NotNull SystemInformation systemInformation, |
| 69 | + final @NotNull ModuleLoader moduleLoader, |
| 70 | + final @Nullable ConfigurationService configService) { |
| 71 | + this.metricRegistry = metricRegistry; |
| 72 | + this.systemInformation = systemInformation; |
| 73 | + this.moduleLoader = moduleLoader; |
| 74 | + this.configService = configService; |
| 75 | + } |
| 76 | + |
| 77 | + public @NotNull Injector bootstrap() throws HiveMQEdgeStartupException { |
| 78 | + metricRegistry.addListener(new MetricRegistryLogger()); |
| 79 | + |
| 80 | + LoggingBootstrap.prepareLogging(); |
| 81 | + |
| 82 | + // Embedded has already called init as it is required to read the config file. |
| 83 | + if (!systemInformation.isEmbedded()) { |
| 84 | + log.trace("Initializing HiveMQ home directory"); |
| 85 | + //Create SystemInformation this early because logging depends on it |
| 86 | + systemInformation.init(); |
| 87 | + } |
| 88 | + |
| 89 | + log.trace("Initializing Logging"); |
| 90 | + LoggingBootstrap.initLogging(systemInformation.getConfigFolder()); |
| 91 | + |
| 92 | + log.trace("Initializing Exception handlers"); |
| 93 | + HiveMQExceptionHandlerBootstrap.addUnrecoverableExceptionHandler(); |
| 94 | + |
| 95 | + //ungraceful shutdown does not delete tmp folders, so we clean them up on broker start |
| 96 | + log.trace("Cleaning up temporary folders"); |
| 97 | + deleteTmpFolder(systemInformation.getDataFolder()); |
| 98 | + |
| 99 | + bootstrapCoreComponents(); |
| 100 | + |
| 101 | + if (configService == null) { |
| 102 | + log.trace("Initializing configuration"); |
| 103 | + configService = ConfigurationBootstrap.bootstrapConfig(systemInformation); |
| 104 | + } |
| 105 | + bootstrapInjector(); |
| 106 | + final long startInit = System.currentTimeMillis(); |
| 107 | + |
| 108 | + bootstrapPersistences(); |
| 109 | + |
| 110 | + // make sure all persistences are bootstrapped. |
| 111 | + awaitPersistenceStartup(); |
| 112 | + |
| 113 | + finishBootstrap(); |
| 114 | + |
| 115 | + log.trace("Initializing classes"); |
| 116 | + Objects.requireNonNull(injector).initEagerSingletons(); |
| 117 | + log.trace("Initialized classes in {}ms", (System.currentTimeMillis() - startInit)); |
| 118 | + return injector; |
| 119 | + } |
| 120 | + |
| 121 | + private void awaitPersistenceStartup() { |
| 122 | + Objects.requireNonNull(injector).persistences(); |
| 123 | + try { |
| 124 | + persistenceStartup.finish(); |
| 125 | + } catch (InterruptedException e) { |
| 126 | + throw new HiveMQEdgeStartupException(e); |
| 127 | + } |
| 128 | + |
| 129 | + // configService is always set in caller |
| 130 | + assert configService != null; |
| 131 | + |
| 132 | + log.info("HiveMQ Edge starts with Persistence Mode: '{}'", |
| 133 | + configService.persistenceConfigurationService().getMode()); |
| 134 | + } |
| 135 | + |
| 136 | + private void bootstrapInjector() { |
| 137 | + log.trace("Initializing injector"); |
| 138 | + final long startDagger = System.currentTimeMillis(); |
| 139 | + injector = DaggerInjector.builder() |
| 140 | + .configurationService(configService) |
| 141 | + .systemInformation(systemInformation) |
| 142 | + .metricRegistry(metricRegistry) |
| 143 | + .persistenceService(persistencesService) |
| 144 | + .handlerService(handlerService) |
| 145 | + .persistenceStartUp(persistenceStartup) |
| 146 | + .moduleLoader(moduleLoader) |
| 147 | + .shutdownHooks(shutdownHooks) |
| 148 | + .capabilityService(capabilityService) |
| 149 | + .restComponentService(restComponentsService) |
| 150 | + .restComponentsHolder(genericAPIHolder) |
| 151 | + .connectionPersistence(connectionPersistence) |
| 152 | + .build(); |
| 153 | + log.trace("Initialized injector in {}ms", (System.currentTimeMillis() - startDagger)); |
| 154 | + } |
| 155 | + |
| 156 | + private void bootstrapCoreComponents() { |
| 157 | + log.info("Integrating Core Modules"); |
| 158 | + // configService is always set in caller |
| 159 | + assert configService != null; |
| 160 | + |
| 161 | + |
| 162 | + try { |
| 163 | + commercialModuleLoaderDiscovery = new CommercialModuleLoaderDiscovery(moduleLoader); |
| 164 | + commercialModuleLoaderDiscovery.discoverModuleLoaderMainClasses(); |
| 165 | + generalBootstrapService = new GeneralBootstrapServiceImpl(shutdownHooks, metricRegistry, systemInformation); |
| 166 | + commercialModuleLoaderDiscovery.generalBootstrap(generalBootstrapService); |
| 167 | + } catch (Exception e) { |
| 168 | + log.warn("Error on loading the commercial module loader.", e); |
| 169 | + throw new HiveMQEdgeStartupException(e); |
| 170 | + } |
| 171 | + } |
| 172 | + |
| 173 | + |
| 174 | + private void bootstrapPersistences() { |
| 175 | + Preconditions.checkNotNull(generalBootstrapService); |
| 176 | + Preconditions.checkNotNull(configService); |
| 177 | + Preconditions.checkNotNull(commercialModuleLoaderDiscovery); |
| 178 | + |
| 179 | + try { |
| 180 | + persistenceBootstrapService = PersistenceBootstrapServiceImpl.decorate(generalBootstrapService, |
| 181 | + configService, |
| 182 | + persistencesService, |
| 183 | + capabilityService); |
| 184 | + commercialModuleLoaderDiscovery.persistenceBootstrap(persistenceBootstrapService); |
| 185 | + } catch (Exception e) { |
| 186 | + log.warn("Error on bootstrapping persistences.", e); |
| 187 | + throw new HiveMQEdgeStartupException(e); |
| 188 | + } |
| 189 | + } |
| 190 | + |
| 191 | + private void finishBootstrap() { |
| 192 | + Preconditions.checkNotNull(injector); |
| 193 | + final Persistences persistences = injector.persistences(); |
| 194 | + Preconditions.checkNotNull(persistences); |
| 195 | + Preconditions.checkNotNull(configService); |
| 196 | + Preconditions.checkNotNull(commercialModuleLoaderDiscovery); |
| 197 | + Preconditions.checkNotNull(persistenceBootstrapService); |
| 198 | + |
| 199 | + try { |
| 200 | + final CompleteBootstrapService completeBootstrapService = CompleteBootstrapServiceImpl.decorate( |
| 201 | + persistenceBootstrapService, |
| 202 | + persistences, |
| 203 | + restComponentsService, |
| 204 | + handlerService); |
| 205 | + commercialModuleLoaderDiscovery.completeBootstrap(completeBootstrapService); |
| 206 | + } catch (Exception e) { |
| 207 | + log.warn("Error on bootstraping persistences.", e); |
| 208 | + throw new HiveMQEdgeStartupException(e); |
| 209 | + } |
| 210 | + } |
| 211 | + |
| 212 | + |
| 213 | + private static void deleteTmpFolder(final @NotNull File dataFolder) { |
| 214 | + final String tmpFolder = dataFolder.getPath() + File.separator + "tmp"; |
| 215 | + try { |
| 216 | + //ungraceful shutdown does not delete tmp folders, so we clean them up on broker start |
| 217 | + FileUtils.deleteDirectory(new File(tmpFolder)); |
| 218 | + } catch (IOException e) { |
| 219 | + //No error because it's not business breaking |
| 220 | + log.warn("The temporary folder could not be deleted ({}).", tmpFolder); |
| 221 | + if (log.isDebugEnabled()) { |
| 222 | + log.debug("Original Exception: ", e); |
| 223 | + } |
| 224 | + } |
| 225 | + } |
| 226 | + |
| 227 | +} |
0 commit comments