All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fish.payara.nucleus.hazelcast.HazelcastCore Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) [2016-2017] Payara Foundation and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://github.com/payara/Payara/blob/master/LICENSE.txt
 * See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * The Payara Foundation designates this particular file as subject to the "Classpath"
 * exception as provided by the Payara Foundation in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package fish.payara.nucleus.hazelcast;

import com.hazelcast.cache.impl.HazelcastServerCachingProvider;
import com.hazelcast.config.Config;
import com.hazelcast.config.ConfigLoader;
import com.hazelcast.config.ExecutorConfig;
import com.hazelcast.config.GlobalSerializerConfig;
import com.hazelcast.config.GroupConfig;
import com.hazelcast.config.MulticastConfig;
import com.hazelcast.config.PartitionGroupConfig;
import com.hazelcast.config.ScheduledExecutorConfig;
import com.hazelcast.config.SerializationConfig;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.nio.serialization.Serializer;
import com.hazelcast.nio.serialization.StreamSerializer;
import fish.payara.nucleus.events.HazelcastEvents;
import fish.payara.nucleus.hazelcast.contextproxy.CachingProviderProxy;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.cache.spi.CachingProvider;
import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.glassfish.api.StartupRunLevel;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.event.EventListener;
import org.glassfish.api.event.EventTypes;
import org.glassfish.api.event.Events;
import org.glassfish.hk2.runlevel.RunLevel;
import org.glassfish.internal.api.ClassLoaderHierarchy;
import org.glassfish.internal.api.JavaEEContextUtil;
import org.glassfish.internal.api.ServerContext;
import org.jvnet.hk2.annotations.Optional;
import org.jvnet.hk2.annotations.Service;

/**
 * The core class for using Hazelcast in Payara
 * @author Steve Millidge (Payara Foundation)
 * @since 4.1.151
 */
@Service(name = "hazelcast-core")
@RunLevel(StartupRunLevel.VAL)
public class HazelcastCore implements EventListener {

    public final static String INSTANCE_ATTRIBUTE = "GLASSFISH-INSTANCE";
    public final static String INSTANCE_GROUP_ATTRIBUTE = "GLASSFISH_INSTANCE_GROUP";
    public static final String CLUSTER_EXECUTOR_SERVICE_NAME="payara-cluster-execution";
    public static final String SCHEDULED_CLUSTER_EXECUTOR_SERVICE_NAME="payara-scheduled-execution";
    private static HazelcastCore theCore;

    private HazelcastInstance theInstance;

    private CachingProvider hazelcastCachingProvider;
    private boolean enabled;
    private boolean booted=false;
    private String memberName;
    private String memberGroup;

    @Inject
    Events events;

    @Inject
    ServerContext context;
    
    @Inject
    ServerEnvironment env;

    @Inject
    @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
    HazelcastRuntimeConfiguration configuration;

    @Inject
    private ClassLoaderHierarchy clh;

    @Inject @Optional
    private JavaEEContextUtil ctxUtil;

    /**
     * Returns the version of the object that has been instantiated.
     * @return null if an instance of {@link HazelcastCore} has not been created
     */
    public static HazelcastCore getCore() {
        return theCore;
    }

    @PostConstruct
    public void postConstruct() {
        theCore = this;
        events.register(this);
        enabled = Boolean.valueOf(configuration.getEnabled());
    }
    
    /**
     * Returns the Hazelcast name of the instance
     * 

* Note this is not the same as the name of the instance config or node * @return {@code Payara} by default * @since 4.1.1.171 */ public String getMemberName() { if (enabled && !booted) { bootstrapHazelcast(); } return memberName; } /** * Gets the name of the member group that this instance belongs to * @return {@code MicroShoal} by default * @since 4.1.1.171 */ public String getMemberGroup() { if (enabled && !booted) { bootstrapHazelcast(); } return memberGroup; } /** * Returns the UUID of the instance. * If Hazelcast is not enabled then a new random one will be returned. * @return a 128-bit immutable universally unique identifier * @since 4.1.1.171 */ public String getUUID() { bootstrapHazelcast(); if (!enabled) { return UUID.randomUUID().toString(); } return theInstance.getCluster().getLocalMember().getUuid(); } /** * Returns true if this instance is a Hazelcast Lite instance * @return * @since 4.1.1.171 */ public boolean isLite() { bootstrapHazelcast(); if (!enabled) { return false; } return theInstance.getCluster().getLocalMember().isLiteMember(); } /** * Gets the actual Hazelcast instance. * Hazelcast will be booted by this method if * it hasn't already started. * @return */ public HazelcastInstance getInstance() { bootstrapHazelcast(); return theInstance; } /** * Gets the JCache provider used by Hazelcast * @return * @see HazelcastCachingProvider */ public CachingProvider getCachingProvider() { bootstrapHazelcast(); return hazelcastCachingProvider; } /** * * @return Whether Hazelcast is currently enabled */ public boolean isEnabled() { return enabled; } @Override public void event(Event event) { if (event.is(EventTypes.SERVER_SHUTDOWN)) { shutdownHazelcast(); } else if (event.is(EventTypes.SERVER_STARTUP)) { bootstrapHazelcast(); } } /** * Sets whether Hazelcast should be enabled. * @param enabled If true will start Hazelcast or restart if currently running; * if false will shut down Hazelcast. */ public void setEnabled(Boolean enabled) { if (!this.enabled && !enabled) { // do nothing } else if (this.enabled && !enabled) { this.enabled = false; shutdownHazelcast(); booted = false; } else if (!this.enabled && enabled) { this.enabled = true; bootstrapHazelcast(); } else if (this.enabled && enabled) { // we need to reboot shutdownHazelcast(); booted =false; bootstrapHazelcast(); } } private Config buildConfiguration() { Config config = new Config(); String hazelcastFilePath = ""; URL serverConfigURL; try { serverConfigURL = new URL(context.getServerConfigURL()); File serverConfigFile = new File(serverConfigURL.getPath()); hazelcastFilePath = serverConfigFile.getParentFile().getAbsolutePath() + File.separator + configuration.getHazelcastConfigurationFile(); File file = new File(hazelcastFilePath); if (file.exists()) { config = ConfigLoader.load(hazelcastFilePath); if (config == null) { Logger.getLogger(HazelcastCore.class.getName()).log(Level.WARNING, "Hazelcast Core could not find configuration file {0} using default configuration", hazelcastFilePath); config = new Config(); } config.setClassLoader(clh.getCommonClassLoader()); if(ctxUtil == null) { Logger.getLogger(HazelcastCore.class.getName()).log(Level.WARNING, "Hazelcast Application Object Serialization Not Available"); } else { SerializationConfig serConfig = config.getSerializationConfig(); if (serConfig == null) { serConfig = new SerializationConfig(); setPayaraSerializerConfig(serConfig); config.setSerializationConfig(serConfig); } else { if(serConfig.getGlobalSerializerConfig() == null) { setPayaraSerializerConfig(serConfig); } else { Serializer ser = serConfig.getGlobalSerializerConfig().getImplementation(); if (ser instanceof StreamSerializer) { config.getSerializationConfig().getGlobalSerializerConfig().setImplementation( new PayaraHazelcastSerializer(ctxUtil, (StreamSerializer) ser)); } else { Logger.getLogger(HazelcastCore.class.getName()).log(Level.WARNING, "Global serializer is not StreamSerializer: {0}", ser.getClass().getName()); } } } } } else { // there is no config override config.setClassLoader(clh.getCommonClassLoader()); if(ctxUtil != null) { SerializationConfig serializationConfig = new SerializationConfig(); setPayaraSerializerConfig(serializationConfig); config.setSerializationConfig(serializationConfig); } MulticastConfig mcConfig = config.getNetworkConfig().getJoin().getMulticastConfig(); config.getNetworkConfig().setPortAutoIncrement(true); mcConfig.setEnabled(true); // check Payara micro overrides mcConfig.setMulticastGroup(configuration.getMulticastGroup()); mcConfig.setMulticastPort(Integer.valueOf(configuration.getMulticastPort())); config.getNetworkConfig().setPort(Integer.valueOf(configuration.getStartPort())); config.setLicenseKey(configuration.getLicenseKey()); config.setLiteMember(Boolean.parseBoolean(configuration.getLite())); // set group config GroupConfig gc = config.getGroupConfig(); gc.setName(configuration.getClusterGroupName()); gc.setPassword(configuration.getClusterGroupPassword()); // build the configuration if ("true".equals(configuration.getHostAwarePartitioning())) { PartitionGroupConfig partitionGroupConfig = config.getPartitionGroupConfig(); partitionGroupConfig.setEnabled(enabled); partitionGroupConfig.setGroupType(PartitionGroupConfig.MemberGroupType.HOST_AWARE); } // build the executor config ExecutorConfig executorConfig = config.getExecutorConfig(CLUSTER_EXECUTOR_SERVICE_NAME); executorConfig.setStatisticsEnabled(true); executorConfig.setPoolSize(Integer.valueOf(configuration.getExecutorPoolSize())); executorConfig.setQueueCapacity(Integer.valueOf(configuration.getExecutorQueueCapacity())); ScheduledExecutorConfig scheduledExecutorConfig = config.getScheduledExecutorConfig(SCHEDULED_CLUSTER_EXECUTOR_SERVICE_NAME); scheduledExecutorConfig.setDurability(1); scheduledExecutorConfig.setCapacity(Integer.valueOf(configuration.getScheduledExecutorQueueCapacity())); scheduledExecutorConfig.setPoolSize(Integer.valueOf(configuration.getScheduledExecutorPoolSize())); config.setProperty("hazelcast.jmx", "true"); } } catch (MalformedURLException ex) { Logger.getLogger(HazelcastCore.class.getName()).log(Level.WARNING, "Unable to parse server config URL", ex); } catch (IOException ex) { Logger.getLogger(HazelcastCore.class.getName()).log(Level.WARNING, "Hazelcast Core could not load configuration file " + hazelcastFilePath + " using default configuration", ex); } return config; } private void setPayaraSerializerConfig(SerializationConfig serConfig) { if(serConfig == null || ctxUtil == null) { throw new IllegalStateException("either serialization config or ctxUtil is null"); } serConfig.setGlobalSerializerConfig(new GlobalSerializerConfig().setImplementation( new PayaraHazelcastSerializer(ctxUtil, null)) .setOverrideJavaSerialization(true)); } private void shutdownHazelcast() { if (theInstance != null) { unbindFromJNDI(); hazelcastCachingProvider.getCacheManager().close(); hazelcastCachingProvider.close(); theInstance.shutdown(); theInstance = null; events.send(new Event(HazelcastEvents.HAZELCAST_SHUTDOWN_COMPLETE)); Logger.getLogger(HazelcastCore.class.getName()).log(Level.INFO, "Shutdown Hazelcast"); } } /** * Starts Hazelcast if not already enabled */ private synchronized void bootstrapHazelcast() { if (!booted && enabled) { Config config = buildConfiguration(); theInstance = Hazelcast.newHazelcastInstance(config); if (env.isMicro()) { memberName = configuration.getMemberName(); memberGroup = configuration.getMemberGroup(); if (Boolean.valueOf(configuration.getGenerateNames()) || memberName == null) { NameGenerator gen = new NameGenerator(); memberName = gen.generateName(); Set clusterMembers = theInstance.getCluster().getMembers(); // If the instance name was generated, we need to compile a list of all the instance names in use within // the instance group, excluding this local instance List takenNames = new ArrayList<>(); for (com.hazelcast.core.Member member : clusterMembers) { if (member != theInstance.getCluster().getLocalMember() && member.getStringAttribute(HazelcastCore.INSTANCE_GROUP_ATTRIBUTE) != null && member.getStringAttribute(HazelcastCore.INSTANCE_GROUP_ATTRIBUTE).equalsIgnoreCase(memberGroup)) { takenNames.add(member.getStringAttribute(HazelcastCore.INSTANCE_ATTRIBUTE)); } } // If our generated name is already in use within the instance group, either generate a new one or set the // name to this instance's UUID if there are no more unique generated options left if (takenNames.contains(memberName)) { memberName = gen.generateUniqueName(takenNames, theInstance.getCluster().getLocalMember().getUuid()); theInstance.getCluster().getLocalMember().setStringAttribute( HazelcastCore.INSTANCE_ATTRIBUTE, memberName); } } } else { if (memberName == null) { memberName = context.getInstanceName(); } if (memberGroup == null) { memberGroup = context.getConfigBean().getConfigRef(); } } theInstance.getCluster().getLocalMember().setStringAttribute(INSTANCE_ATTRIBUTE, memberName); theInstance.getCluster().getLocalMember().setStringAttribute(INSTANCE_GROUP_ATTRIBUTE, memberGroup); hazelcastCachingProvider = new CachingProviderProxy(HazelcastServerCachingProvider.createCachingProvider(theInstance), context); events.send(new Event(HazelcastEvents.HAZELCAST_BOOTSTRAP_COMPLETE)); bindToJNDI(); booted = true; } } private void bindToJNDI() { try { InitialContext ctx; ctx = new InitialContext(); ctx.bind(configuration.getJNDIName(), theInstance); ctx.bind(configuration.getCachingProviderJNDIName(), hazelcastCachingProvider); ctx.bind(configuration.getCacheManagerJNDIName(), hazelcastCachingProvider.getCacheManager()); Logger.getLogger(HazelcastCore.class.getName()).log(Level.INFO, "Hazelcast Instance Bound to JNDI at {0}", configuration.getJNDIName()); Logger.getLogger(HazelcastCore.class.getName()).log(Level.INFO, "JSR107 Caching Provider Bound to JNDI at {0}", configuration.getCachingProviderJNDIName()); Logger.getLogger(HazelcastCore.class.getName()).log(Level.INFO, "JSR107 Default Cache Manager Bound to JNDI at {0}", configuration.getCacheManagerJNDIName()); } catch (NamingException ex) { Logger.getLogger(HazelcastCore.class.getName()).log(Level.SEVERE, null, ex); } } private void unbindFromJNDI() { try { InitialContext ctx; ctx = new InitialContext(); ctx.unbind(configuration.getJNDIName()); ctx.unbind(configuration.getCacheManagerJNDIName()); ctx.unbind(configuration.getCachingProviderJNDIName()); Logger.getLogger(HazelcastCore.class.getName()).log(Level.INFO, "Hazelcast Instance Unbound from JNDI at {0}", configuration.getJNDIName()); Logger.getLogger(HazelcastCore.class.getName()).log(Level.INFO, "JSR107 Caching Provider Unbound from JNDI at {0}", configuration.getCachingProviderJNDIName()); Logger.getLogger(HazelcastCore.class.getName()).log(Level.INFO, "JSR107 Cache Manager Unbound from JNDI at {0}", configuration.getCacheManagerJNDIName()); } catch (NamingException ex) { Logger.getLogger(HazelcastCore.class.getName()).log(Level.SEVERE, null, ex); } } /** * Gets the port that Hazelcast in running on * @return The default is {@link 54327} */ public int getPort() { return theInstance.getCluster().getLocalMember().getSocketAddress().getPort(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy