| /* |
| * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package org.glassfish.enterprise.iiop.impl; |
| |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.logging.Logger; |
| import java.util.logging.Level; |
| |
| import com.sun.enterprise.ee.cms.core.FailureNotificationSignal; |
| import com.sun.enterprise.ee.cms.core.JoinedAndReadyNotificationSignal; |
| import com.sun.enterprise.ee.cms.core.PlannedShutdownSignal; |
| import com.sun.enterprise.ee.cms.core.Signal; |
| import com.sun.enterprise.ee.cms.core.SignalAcquireException; |
| import com.sun.enterprise.ee.cms.core.SignalReleaseException; |
| import com.sun.logging.LogDomains; |
| |
| import com.sun.corba.ee.spi.orb.ORB ; |
| import com.sun.corba.ee.spi.folb.ClusterInstanceInfo; |
| import com.sun.corba.ee.spi.folb.GroupInfoService; |
| import com.sun.corba.ee.impl.folb.GroupInfoServiceBase; |
| import com.sun.corba.ee.spi.folb.GroupInfoServiceObserver; |
| import com.sun.corba.ee.spi.folb.SocketInfo; |
| import com.sun.corba.ee.spi.misc.ORBConstants; |
| import com.sun.enterprise.config.serverbeans.Cluster; |
| import com.sun.enterprise.config.serverbeans.Config; |
| import com.sun.enterprise.config.serverbeans.Configs; |
| import com.sun.enterprise.config.serverbeans.Domain; |
| import org.glassfish.orb.admin.config.IiopListener; |
| import org.glassfish.orb.admin.config.IiopService; |
| import com.sun.enterprise.config.serverbeans.Server; |
| import com.sun.enterprise.config.serverbeans.Servers; |
| import com.sun.enterprise.config.serverbeans.Nodes; |
| import com.sun.enterprise.config.serverbeans.Node; |
| import com.sun.enterprise.ee.cms.core.CallBack; |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| import java.util.ArrayList; |
| import org.glassfish.config.support.GlassFishConfigBean; |
| import org.glassfish.config.support.PropertyResolver; |
| import org.glassfish.gms.bootstrap.GMSAdapter; |
| import org.glassfish.gms.bootstrap.GMSAdapterService; |
| import org.glassfish.hk2.api.ServiceLocator; |
| import org.omg.CORBA.ORBPackage.InvalidName; |
| |
| // REVISIT impl |
| //import com.sun.corba.ee.impl.folb.ServerGroupManager; |
| |
| /** |
| * @author Harold Carr |
| */ |
| public class IiopFolbGmsClient implements CallBack { |
| |
| private static final Logger _logger = LogDomains.getLogger(IiopFolbGmsClient.class, LogDomains.CORBA_LOGGER); |
| |
| private ServiceLocator services; |
| |
| private Domain domain ; |
| |
| private Server myServer ; |
| |
| private Nodes nodes ; |
| |
| private GMSAdapterService gmsAdapterService ; |
| |
| private GMSAdapter gmsAdapter ; |
| |
| private Map<String, ClusterInstanceInfo> currentMembers; |
| |
| private GroupInfoService gis; |
| |
| private void fineLog( String fmt, Object... args ) { |
| if (_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, fmt, args); |
| } |
| } |
| |
| |
| public IiopFolbGmsClient(ServiceLocator services) { |
| fineLog("IiopFolbGmsClient: constructor: services {0}", services); |
| this.services = services; |
| |
| gmsAdapterService = services.getService(GMSAdapterService.class); |
| |
| try { |
| if (gmsAdapterService == null) { |
| return; |
| } |
| |
| gmsAdapter = gmsAdapterService.getGMSAdapter(); |
| fineLog("IiopFolbGmsClient: gmsAdapter {0}", gmsAdapter); |
| |
| if (gmsAdapter != null) { |
| domain = services.getService(Domain.class); |
| fineLog("IiopFolbGmsClient: domain {0}", domain); |
| |
| Servers servers = services.getService(Servers.class); |
| fineLog("IiopFolbGmsClient: servers {0}", servers); |
| |
| nodes = services.getService(Nodes.class); |
| fineLog("IiopFolbGmsClient: nodes {0}", nodes); |
| |
| String instanceName = gmsAdapter.getModule().getInstanceName(); |
| fineLog("IiopFolbGmsClient: instanceName {0}", instanceName); |
| |
| myServer = servers.getServer(instanceName); |
| fineLog("IiopFolbGmsClient: myServer {0}", myServer); |
| |
| gis = new GroupInfoServiceGMSImpl(); |
| fineLog("IiopFolbGmsClient: IIOP GIS created"); |
| |
| currentMembers = getAllClusterInstanceInfo(); |
| fineLog("IiopFolbGmsClient: currentMembers = ", currentMembers); |
| |
| fineLog("iiop instance info = " + getIIOPEndpoints()); |
| |
| gmsAdapter.registerFailureNotificationListener(this); |
| gmsAdapter.registerJoinedAndReadyNotificationListener(this); |
| gmsAdapter.registerPlannedShutdownListener(this); |
| |
| fineLog("IiopFolbGmsClient: GMS action factories added"); |
| } else { |
| fineLog("IiopFolbGmsClient: gmsAdapterService is null"); |
| gis = new GroupInfoServiceNoGMSImpl(); |
| } |
| |
| } catch (Throwable t) { |
| _logger.log(Level.SEVERE, t.getLocalizedMessage(), t); |
| } finally { |
| fineLog("IiopFolbGmsClient: gmsAdapter {0}", gmsAdapter); |
| } |
| } |
| |
| |
| public void setORB(ORB orb) { |
| try { |
| orb.register_initial_reference(ORBConstants.FOLB_SERVER_GROUP_INFO_SERVICE, (org.omg.CORBA.Object) gis); |
| fineLog(".initGIS: naming registration complete: {0}", gis); |
| |
| // Just for logging |
| GroupInfoService gisRef = (GroupInfoService) orb |
| .resolve_initial_references(ORBConstants.FOLB_SERVER_GROUP_INFO_SERVICE); |
| List<ClusterInstanceInfo> lcii = gisRef.getClusterInstanceInfo(null); |
| fineLog("Results from getClusterInstanceInfo:"); |
| if (lcii != null) { |
| for (ClusterInstanceInfo cii : lcii) { |
| fineLog(cii.toString()); |
| } |
| } |
| } catch (InvalidName e) { |
| fineLog(".initGIS: registering GIS failed: {0}", e); |
| } |
| } |
| |
| public GroupInfoService getGroupInfoService() { |
| return gis ; |
| } |
| |
| public boolean isGMSAvailable() { |
| return gmsAdapter != null ; |
| } |
| |
| //////////////////////////////////////////////////// |
| // |
| // Action |
| // |
| |
| @Override |
| public void processNotification(final Signal signal) { |
| try { |
| fineLog("processNotification: signal {0}", signal); |
| signal.acquire(); |
| handleSignal(signal); |
| } catch (SignalAcquireException e) { |
| _logger.log(Level.SEVERE, e.getLocalizedMessage()); |
| } catch (Throwable t) { |
| _logger.log(Level.SEVERE, t.getLocalizedMessage(), t); |
| } finally { |
| try { |
| signal.release(); |
| } catch (SignalReleaseException e) { |
| _logger.log(Level.SEVERE, e.getLocalizedMessage()); |
| } |
| } |
| } |
| |
| //////////////////////////////////////////////////// |
| // |
| // Implementation |
| // |
| |
| |
| private void handleSignal(final Signal signal) { |
| fineLog("IiopFolbGmsClient.handleSignal: signal from: {0}", signal.getMemberToken()); |
| fineLog("IiopFolbGmsClient.handleSignal: map entryset: {0}", signal.getMemberDetails().entrySet()); |
| |
| if (signal instanceof PlannedShutdownSignal || signal instanceof FailureNotificationSignal) { |
| removeMember(signal); |
| } else if (signal instanceof JoinedAndReadyNotificationSignal) { |
| addMember(signal); |
| } else { |
| _logger.log(Level.SEVERE, "IiopFolbGmsClient.handleSignal: unknown signal: {0}", signal.toString()); |
| } |
| } |
| |
| |
| private void removeMember(final Signal signal) { |
| String instanceName = signal.getMemberToken(); |
| try { |
| fineLog("IiopFolbGmsClient.removeMember->: {0}", instanceName); |
| |
| synchronized (this) { |
| if (currentMembers.get(instanceName) != null) { |
| currentMembers.remove(instanceName); |
| |
| fineLog("IiopFolbGmsClient.removeMember: {0} removed - notifying listeners", instanceName); |
| |
| gis.notifyObservers(); |
| |
| fineLog("IiopFolbGmsClient.removeMember: {0} - notification complete", instanceName); |
| } else { |
| fineLog("IiopFolbGmsClient.removeMember: {0} not present: no action", instanceName); |
| } |
| } |
| } finally { |
| fineLog("IiopFolbGmsClient.removeMember<-: {0}", instanceName); |
| } |
| } |
| |
| |
| private void addMember(final Signal signal) { |
| final String instanceName = signal.getMemberToken(); |
| try { |
| fineLog("IiopFolbGmsClient.addMember->: {0}", instanceName); |
| |
| synchronized (this) { |
| if (currentMembers.get(instanceName) != null) { |
| fineLog("IiopFolbGmsClient.addMember: {0} already present: no action", instanceName); |
| } else { |
| ClusterInstanceInfo clusterInstanceInfo = getClusterInstanceInfo(instanceName); |
| |
| currentMembers.put(clusterInstanceInfo.name(), clusterInstanceInfo); |
| |
| fineLog("IiopFolbGmsClient.addMember: {0} added - notifying listeners", instanceName); |
| |
| gis.notifyObservers(); |
| |
| fineLog("IiopFolbGmsClient.addMember: {0} - notification complete", instanceName); |
| } |
| } |
| } finally { |
| fineLog("IiopFolbGmsClient.addMember<-: {0}", instanceName); |
| } |
| } |
| |
| |
| private int resolvePort(Server server, IiopListener listener) { |
| fineLog("resolvePort: server {0} listener {1}", server, listener); |
| |
| IiopListener ilRaw = GlassFishConfigBean.getRawView(listener); |
| fineLog("resolvePort: ilRaw {0}", ilRaw); |
| |
| PropertyResolver pr = new PropertyResolver(domain, server.getName()); |
| fineLog("resolvePort: pr {0}", pr); |
| |
| String port = pr.getPropertyValue(ilRaw.getPort()); |
| fineLog("resolvePort: port {0}", port); |
| |
| return Integer.parseInt(port); |
| } |
| |
| |
| private ClusterInstanceInfo getClusterInstanceInfo(Server server, Config config, boolean assumeInstanceIsRunning) { |
| if (server == null) { |
| return null; |
| } |
| |
| if (!assumeInstanceIsRunning) { |
| if (!server.isRunning()) { |
| return null; |
| } |
| } |
| |
| fineLog("getClusterInstanceInfo: server {0}, config {1}", server, config); |
| |
| final String name = server.getName(); |
| fineLog("getClusterInstanceInfo: name {0}", name); |
| |
| final int weight = Integer.parseInt(server.getLbWeight()); |
| fineLog("getClusterInstanceInfo: weight {0}", weight); |
| |
| final String nodeName = server.getNodeRef(); |
| String hostName = nodeName; |
| if (nodes != null) { |
| Node node = nodes.getNode(nodeName); |
| if (node != null) { |
| if (node.isLocal()) { |
| try { |
| hostName = InetAddress.getLocalHost().getHostName(); |
| } catch (UnknownHostException exc) { |
| fineLog("getClusterInstanceInfo: caught exception for localhost lookup {0}", exc); |
| } |
| } else { |
| hostName = node.getNodeHost(); |
| } |
| } |
| } |
| |
| fineLog("getClusterInstanceInfo: host {0}", hostName); |
| |
| final IiopService iservice = config.getExtensionByType(IiopService.class); |
| fineLog("getClusterInstanceInfo: iservice {0}", iservice); |
| |
| final List<IiopListener> listeners = iservice.getIiopListener(); |
| fineLog("getClusterInstanceInfo: listeners {0}", listeners); |
| |
| final List<SocketInfo> sinfos = new ArrayList<>(); |
| for (IiopListener il : listeners) { |
| SocketInfo sinfo = new SocketInfo(il.getId(), hostName, resolvePort(server, il)); |
| sinfos.add(sinfo); |
| } |
| fineLog("getClusterInstanceInfo: sinfos {0}", sinfos); |
| |
| final ClusterInstanceInfo result = new ClusterInstanceInfo(name, weight, sinfos); |
| fineLog("getClusterInstanceInfo: result {0}", result); |
| |
| return result; |
| } |
| |
| |
| private Config getConfigForServer(Server server) { |
| fineLog("getConfigForServer: server {0}", server); |
| |
| String configRef = server.getConfigRef(); |
| fineLog("getConfigForServer: configRef {0}", configRef); |
| |
| Configs configs = services.getService(Configs.class); |
| fineLog("getConfigForServer: configs {0}", configs); |
| |
| Config config = configs.getConfigByName(configRef); |
| fineLog("getConfigForServer: config {0}", config); |
| |
| return config; |
| } |
| |
| |
| // For addMember. |
| private ClusterInstanceInfo getClusterInstanceInfo(String instanceName) { |
| fineLog("getClusterInstanceInfo: instanceName {0}", instanceName); |
| |
| final Servers servers = services.getService(Servers.class); |
| fineLog("getClusterInstanceInfo: servers {0}", servers); |
| |
| final Server server = servers.getServer(instanceName); |
| fineLog("getClusterInstanceInfo: server {0}", server); |
| |
| final Config config = getConfigForServer(server); |
| fineLog("getClusterInstanceInfo: servers {0}", servers); |
| |
| // assumeInstanceIsRunning is set to true since this is |
| // coming from addMember, because shoal just told us that the instance is up. |
| ClusterInstanceInfo result = getClusterInstanceInfo(server, config, true); |
| fineLog("getClusterInstanceInfo: result {0}", result); |
| |
| return result; |
| } |
| |
| |
| private Map<String, ClusterInstanceInfo> getAllClusterInstanceInfo() { |
| final Cluster myCluster = myServer.getCluster(); |
| fineLog("getAllClusterInstanceInfo: myCluster {0}", myCluster); |
| |
| final Config myConfig = getConfigForServer(myServer); |
| fineLog("getAllClusterInstanceInfo: myConfig {0}", myConfig); |
| |
| final Map<String, ClusterInstanceInfo> result = new HashMap<>(); |
| |
| // When myServer is DAS's situation, myCluster is null. |
| // null check is needed. |
| if (myCluster != null) { |
| for (Server server : myCluster.getInstances()) { |
| ClusterInstanceInfo cii = getClusterInstanceInfo(server, myConfig, false); |
| if (cii != null) { |
| result.put(server.getName(), cii); |
| } |
| } |
| } |
| |
| fineLog("getAllClusterInstanceInfo: result {0}", result); |
| return result; |
| } |
| |
| |
| // return host:port,... string for all clear text ports in the cluster |
| // instance info. |
| public final String getIIOPEndpoints() { |
| final Map<String, ClusterInstanceInfo> cinfos = getAllClusterInstanceInfo(); |
| final StringBuilder result = new StringBuilder(); |
| boolean first = true; |
| for (ClusterInstanceInfo cinfo : cinfos.values()) { |
| for (SocketInfo sinfo : cinfo.endpoints()) { |
| if (!sinfo.type().startsWith("SSL")) { |
| if (first) { |
| first = false; |
| } else { |
| result.append(','); |
| } |
| |
| result.append(sinfo.host()).append(':').append(sinfo.port()); |
| } |
| } |
| } |
| return result.toString(); |
| } |
| |
| |
| class GroupInfoServiceGMSImpl extends GroupInfoServiceBase { |
| |
| @Override |
| public List<ClusterInstanceInfo> internalClusterInstanceInfo(List<String> endpoints) { |
| fineLog("internalClusterInstanceInfo: currentMembers {0}", currentMembers); |
| |
| if (currentMembers == null) { |
| return new ArrayList<>(); |
| } else { |
| return new ArrayList<>(currentMembers.values()); |
| } |
| } |
| } |
| |
| class GroupInfoServiceNoGMSImpl extends GroupInfoServiceGMSImpl { |
| |
| @Override |
| public boolean addObserver(GroupInfoServiceObserver x) { |
| throw new RuntimeException("SHOULD NOT BE CALLED"); |
| } |
| |
| |
| @Override |
| public void notifyObservers() { |
| throw new RuntimeException("SHOULD NOT BE CALLED"); |
| } |
| |
| |
| @Override |
| public boolean shouldAddAddressesToNonReferenceFactory(String[] x) { |
| throw new RuntimeException("SHOULD NOT BE CALLED"); |
| } |
| |
| |
| @Override |
| public boolean shouldAddMembershipLabel(String[] adapterName) { |
| throw new RuntimeException("SHOULD NOT BE CALLED"); |
| } |
| } |
| } |