I ran ports and instance for these new changes. If it looks ok I'll
check it in. Attached are the source.
Running cluster now.
Index: src/main/java/com/sun/enterprise/config/serverbeans/ServerHelper.java
===================================================================
---
src/main/java/com/sun/enterprise/config/serverbeans/ServerHelper.java
(revision 39006)
+++
src/main/java/com/sun/enterprise/config/serverbeans/ServerHelper.java
(working copy)
@@ -52,9 +52,9 @@
*
* @author Byron Nevins
*/
-class ServerHelper {
+public class ServerHelper {
- ServerHelper(Server theServer, Config theConfig) {
+ public ServerHelper(Server theServer, Config theConfig) {
server = theServer;
config = theConfig;
@@ -84,13 +84,17 @@
}
String getHost() {
- String hostName = null;
Dom serverDom = Dom.unwrap(server);
Nodes nodes = serverDom.getHabitat().getComponent(Nodes.class);
if (server == null || nodes == null) {
return null;
}
+ return getHost(nodes);
+ }
+
+ public String getHost(Nodes nodes) {
+ String hostName = null;
// Get it from the node associated with the server
String nodeName = server.getNode();
if (StringUtils.ok(nodeName)) {
Index: src/main/java/com/sun/enterprise/config/util/PortManager.java
===================================================================
--- src/main/java/com/sun/enterprise/config/util/PortManager.java
(revision 39006)
+++ src/main/java/com/sun/enterprise/config/util/PortManager.java
(working copy)
@@ -39,6 +39,7 @@
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.config.serverbeans.ServerHelper;
import com.sun.enterprise.config.serverbeans.SystemProperty;
import com.sun.enterprise.util.ObjectAnalyzer;
import com.sun.enterprise.util.StringUtils;
@@ -62,8 +63,9 @@
newServer = theNewServer;
domain = theDomain;
+ ServerHelper helper = new ServerHelper(newServer, config);
serverName = newServer.getName();
- host = newServer.getHost();
+ host = helper.getHost(domain.getNodes());
allPorts = new ArrayList<Integer>();
newServerPorts = new ServerPorts(cluster, config, domain,
newServer);
On 7/23/2010 7:45 PM, Byron Nevins wrote:
> Can you try it on devtests and see if it works?
>
>
> On 7/23/2010 11:42 AM, Jennifer Chou wrote:
>> ok sounds good. not checking anything in.
>>
>> On 7/23/2010 7:32 PM, Byron Nevins wrote:
>>> I recommend NOT doing this. We should have this ugly code in one
>>> and only one place. ServerHelper has those lines now. It just
>>> needs to be refactored into another method in ServerHelper where you
>>> call it with a Nodes or Node object...
>>>
>>>
>>> On 7/23/2010 10:44 AM, Jennifer Chou wrote:
>>>> Here's the patch I was going to checkin. just running ql on it
>>>> right now. Let me know if you want me to go ahead with checking in.
>>>> I was thinking that since server being created as passed to
>>>> PortManager. Then port manager calls the getHost duck typed method
>>>> on Server which I think may not have that info yet?
>>>> So I removed call to duck typed method server.getHost in PortManager.
>>>>
>>>> Index: src/main/java/com/sun/enterprise/config/util/PortManager.java
>>>> ===================================================================
>>>> ---
>>>> src/main/java/com/sun/enterprise/config/util/PortManager.java
>>>> (revisio
>>>> n 39006)
>>>> +++
>>>> src/main/java/com/sun/enterprise/config/util/PortManager.java
>>>> (working
>>>> copy)
>>>> @@ -38,6 +38,7 @@
>>>> import com.sun.enterprise.config.serverbeans.Cluster;
>>>> import com.sun.enterprise.config.serverbeans.Config;
>>>> import com.sun.enterprise.config.serverbeans.Domain;
>>>> +import com.sun.enterprise.config.serverbeans.Node;
>>>> import com.sun.enterprise.config.serverbeans.Server;
>>>> import com.sun.enterprise.config.serverbeans.SystemProperty;
>>>> import com.sun.enterprise.util.ObjectAnalyzer;
>>>> @@ -63,12 +64,26 @@
>>>> newServer = theNewServer;
>>>> domain = theDomain;
>>>> serverName = newServer.getName();
>>>> - host = newServer.getHost();
>>>> + String nodeName = newServer.getNode();
>>>> + if (!StringUtils.ok(nodeName))
>>>> + throw new
>>>> TransactionFailure(Strings.get("PortManager.noNodeSpecified",
>>>> serverName));
>>>> +
>>>> + Node node = domain.getNodeNamed(nodeName);
>>>> + if (node == null)
>>>> + throw new
>>>> TransactionFailure(Strings.get("PortManager.noNode",nodeName));
>>>> +
>>>> + host = node.getNodeHost();
>>>> + // XXX Hack to get around the fact that the default
>>>> localhost
>>>> + // node entry is malformed
>>>> + if (host == null && nodeName.equals("localhost")) {
>>>> + host = "localhost";
>>>> + }
>>>> +
>>>> allPorts = new ArrayList<Integer>();
>>>> newServerPorts = new ServerPorts(cluster, config,
>>>> domain, newServer);
>>>>
>>>> if (!StringUtils.ok(host))
>>>> - throw new
>>>> TransactionFailure(Strings.get("PortManager.noHost",serverName));
>>>> + throw new
>>>> TransactionFailure(Strings.get("PortManager.noHost",nodeName));
>>>>
>>>> isLocal = NetUtils.IsThisHostLocal(host);
>>>>
>>>> @@ -249,7 +264,7 @@
>>>> private final Server newServer;
>>>> private final boolean isLocal;
>>>> private final Domain domain;
>>>> - private final String host;
>>>> + private String host = null;
>>>> private final List<Integer> allPorts;
>>>> private final List<Server> allServers;
>>>> private final List<ServerPorts> serversOnHost;
>>>>
>>>> Index:
>>>> src/main/java/com/sun/enterprise/config/util/LocalStrings.properties
>>>> ===================================================================
>>>> ---
>>>> src/main/java/com/sun/enterprise/config/util/LocalStrings.properties
>>>> (revision 39006)
>>>> +++
>>>> src/main/java/com/sun/enterprise/config/util/LocalStrings.properties
>>>> (working copy)
>>>> @@ -3,7 +3,9 @@
>>>> PortUtils.duplicate_port=Found two system-property elements with
>>>> the same port
>>>> number ({0}) for {1}.
>>>> PortUtils.non_int_port=Found a system-property with a non-integer
>>>> port number (
>>>> {0}) for {1}.
>>>> PortUtils.illegal_port_number=The supplied port number, {0}, for
>>>> the server, {1
>>>> }, is illegal. Legal values are 0 to {2} inclusive.
>>>> -PortManager.noHost=There is no node-agent-ref specified for the
>>>> instance {0}.
>>>> +PortManager.noNodeSpecified=There is no node specified for the
>>>> instance {0}.
>>>> +PortManager.noNode=Node {0} does not exist.
>>>> +PortManager.noHost=Node host is not specified on node {0}.
>>>> PortManager.noFreePort=Can''t locate a free port. None of the
>>>> ports between {0
>>>> } and {1} are available.
>>>>
>>>> On 7/23/2010 6:35 PM, Byron Nevins wrote:
>>>>> I just changed things last night -- I'll take a look.
>>>>>
>>>>> Jennifer -- Server.getHostName() on DAS returns null!!! I'll fix
>>>>> it...
>>>>>
>>>>> On 7/23/2010 9:49 AM, Jennifer Chou wrote:
>>>>>> working on fix right now.
>>>>>>
>>>>>> On 7/23/2010 5:39 PM, Tom Mueller wrote:
>>>>>>> Yes.
>>>>>>> Tom
>>>>>>>
>>>>>>> On 7/23/2010 11:37 AM, Tim Quinn wrote:
>>>>>>>> Hi.
>>>>>>>>
>>>>>>>> The Hudson admin job is red with (among other things) this
>>>>>>>> error when trying to create an instance:
>>>>>>>>
>>>>>>>> [java] remote failure: Exception while adding the new configuration org.jvnet.hk2.config.TransactionFailure: There is no node-agent-ref specified for the instance in_892228. : org.jvnet.hk2.config.TransactionFailure: There is no node-agent-ref specified for the instance in_892228.
>>>>>>>>
>>>>>>>>
>>>>>>>> We are seeing the same error in the deployment devtests in
>>>>>>>> trying to create an instance.
>>>>>>>> Is someone looking into this?
>>>>>>>> - Tim
>>>>>>
>>>>>
>>>>
>>>
>>> --
>>> Byron Nevins - Oracle Corporation
>>> Home: 650-359-1290
>>> Cell: 650-784-4123
>>> Sierra: 209-295-2188
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: admin-unsubscribe_at_glassfish.dev.java.net For
>>> additional commands, e-mail: admin-help_at_glassfish.dev.java.net
>>
>
> --
> Byron Nevins - Oracle Corporation
> Home: 650-359-1290
> Cell: 650-784-4123
> Sierra: 209-295-2188
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: admin-unsubscribe_at_glassfish.dev.java.net For
> additional commands, e-mail: admin-help_at_glassfish.dev.java.net
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2010 Sun Microsystems, Inc. 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://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/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/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [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 com.sun.enterprise.config.util;
import com.sun.enterprise.config.serverbeans.Cluster;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.ServerHelper;
import com.sun.enterprise.config.serverbeans.SystemProperty;
import com.sun.enterprise.util.ObjectAnalyzer;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.util.Utility;
import com.sun.enterprise.util.net.*;
import java.beans.PropertyVetoException;
import java.util.*;
import org.jvnet.hk2.config.TransactionFailure;
/**
* Hiding place for the remarkably complex logic of assigning ports to instances
* GUARANTEE -- the only thing thrown from here is TransactionFailure
* @author Byron Nevins
*/
public final class PortManager {
public PortManager(Cluster cluster, Config config, Domain theDomain, Server theNewServer) throws TransactionFailure {
try {
if (theNewServer == null || theDomain == null)
throw new TransactionFailure(Strings.get("internal.error", "null argument in PortManager constructor"));
newServer = theNewServer;
domain = theDomain;
ServerHelper helper = new ServerHelper(newServer, config);
serverName = newServer.getName();
host = helper.getHost(domain.getNodes());
allPorts = new ArrayList<Integer>();
newServerPorts = new ServerPorts(cluster, config, domain, newServer);
if (!StringUtils.ok(host))
throw new TransactionFailure(Strings.get("PortManager.noHost", serverName));
isLocal = NetUtils.IsThisHostLocal(host);
allServers = domain.getServers().getServer();
// why all this nonsense? ConcurrentModificationException!!!
for (Iterator<Server> it = allServers.iterator(); it.hasNext();) {
Server curr = it.next();
if (serverName.equals(curr.getName())) {
it.remove();
}
}
serversOnHost = new ArrayList<ServerPorts>();
}
catch (TransactionFailure tf) {
throw tf;
}
catch (Exception e) {
// this Exception will not take just a Throwable. I MUST give a string
throw new TransactionFailure(e.toString(), e);
}
}
public void process() throws TransactionFailure {
try {
// if there are no port system-property's -- no point in going on!
if (newServerPorts.getMap().isEmpty())
return; // all done!
// make sure user-supplied props are not flaky
PortUtils.checkInternalConsistency(newServer);
// create a list of ALL servers running on the same machine
createServerList();
// create a sorted list of every port on every other server on the same machine.
createAllPortsList();
// we have a list of all possible conflicting server ports.
// let's find some unused ports and reassign the variables inside
// the ServerPorts class
Map<String, Integer> reassigned = reassignPorts();
Set<Map.Entry<String, Integer>> entries = reassigned.entrySet();
List<SystemProperty> sps = newServer.getSystemProperty();
for (Map.Entry<String, Integer> entry : entries) {
String name = entry.getKey();
int port = entry.getValue();
changeSystemProperty(sps, name, "" + port); // do not want commas in the int!
}
}
catch (Exception e) {
throw new TransactionFailure(e.toString(), e);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("PortManager Dump:");
for (ServerPorts sp : serversOnHost)
sb.append(sp).append('\n');
sb.append("All Ports in all other servers on same host: " + allPorts);
return sb.toString();
}
private void createServerList() {
if (isLocal)
createLocalServerList();
else
createRemoteServerList();
}
private void createLocalServerList() {
for (Server server : allServers) {
if (server.isDas())
serversOnHost.add(new ServerPorts(domain, server));
else if (NetUtils.IsThisHostLocal(server.getNode()))
serversOnHost.add(new ServerPorts(domain, server));
}
}
private void createRemoteServerList() {
for (Server server : allServers) {
// no DAS!
if (server.isInstance() && sameHost(server))
serversOnHost.add(new ServerPorts(domain, server));
}
}
private boolean sameHost(Server server) {
return NetUtils.isEqual(server.getNode(), host);
}
private Map<String, Integer> reassignPorts() throws TransactionFailure {
// inefficient, probably a slicker way to do it. Not worth the effort
// there are at most 8 items...
Map<String, Integer> portProps = newServerPorts.getMap();
Map<String, Integer> changedPortProps = new HashMap<String, Integer>();
Set<Map.Entry<String, Integer>> entries = portProps.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
String name = entry.getKey();
Integer num = entry.getValue();
Integer newNum = reassignPort(num);
if (!newNum.equals(num))
changedPortProps.put(name, newNum);
}
return changedPortProps;
}
private Integer reassignPort(Integer num) throws TransactionFailure {
int max = num + 100;
while (num < max) {
num = getNextUnassignedPort(num);
if (isPortFree(num))
return num;
else
++num;
}
throw new TransactionFailure(Strings.get("PortManager.noFreePort"));
}
private Integer getNextUnassignedPort(Integer num) throws TransactionFailure {
int max = num + MAX_PORT_TRIES; // to avoid infinite loop
for (int inum = num; inum < max; inum++) {
if (!allPorts.contains(inum))
return inum;
}
throw new TransactionFailure(Strings.get("PortManager.noFreePort", num, max));
}
private void changeSystemProperty(List<SystemProperty> sps, String name, String port) throws PropertyVetoException, TransactionFailure {
for (SystemProperty sp : sps) {
if (name.equals(sp.getName())) {
sp.setValue(port);
return;
}
}
// does not exist -- let's add one!
SystemProperty sp = newServer.createChild(SystemProperty.class);
sp.setName(name);
sp.setValue(port);
sps.add(sp);
}
private boolean isPortFree(int num) {
if (isLocal)
return NetUtils.isPortFree(num);
return NetUtils.isPortFree(host, num);
}
private void createAllPortsList() {
for (ServerPorts sp : serversOnHost) {
Collection<Integer> ii = sp.getMap().values();
// do not want duplicates!!
for (Integer i : ii)
if (!allPorts.contains(i))
allPorts.add(i);
}
Collections.sort(allPorts);
}
private final String serverName;
private final Server newServer;
private final boolean isLocal;
private final Domain domain;
private final String host;
private final List<Integer> allPorts;
private final List<Server> allServers;
private final List<ServerPorts> serversOnHost;
private final ServerPorts newServerPorts;
private final boolean checkLivePorts = true;
private static final int MAX_PORT_TRIES = 1100;
}
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2010 Sun Microsystems, Inc. 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://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/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/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [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 com.sun.enterprise.config.serverbeans;
import com.sun.enterprise.config.serverbeans.*;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.util.net.NetUtils;
import com.sun.grizzly.config.dom.NetworkListener;
import java.util.List;
import org.glassfish.config.support.GlassFishConfigBean;
import org.glassfish.config.support.PropertyResolver;
import org.jvnet.hk2.config.Dom;
/**
* The Server.java file is getting pretty bloated.
* Offload some utilities here.
* Nothing in here is visible outside this package...
*
* @author Byron Nevins
*/
public class ServerHelper {
public ServerHelper(Server theServer, Config theConfig) {
server = theServer;
config = theConfig;
if(server == null || config == null)
throw new IllegalArgumentException();
}
int getAdminPort() {
try {
if (server == null)
return -1;
if (config == null)
return -1;
String portString = getAdminPortString(server, config);
if (portString == null)
return -1; // get out quick. it is kosher to call with a null Server
return Integer.parseInt(portString);
}
catch (Exception e) {
// drop through...
}
return -1;
}
String getHost() {
Dom serverDom = Dom.unwrap(server);
Nodes nodes = serverDom.getHabitat().getComponent(Nodes.class);
if (server == null || nodes == null) {
return null;
}
return getHost(nodes);
}
public String getHost(Nodes nodes) {
String hostName = null;
// Get it from the node associated with the server
String nodeName = server.getNode();
if (StringUtils.ok(nodeName)) {
Node node = nodes.getNode(nodeName);
if (node != null) {
hostName = node.getNodeHost();
}
// XXX Hack to get around the fact that the default localhost
// node entry is malformed
if (hostName == null && nodeName.equals("localhost")) {
hostName = "localhost";
}
}
if (StringUtils.ok(hostName)) {
return hostName;
}
else {
return null;
}
}
// very simple generic check
boolean isRunning() {
try {
return NetUtils.isRunning(getHost(), getAdminPort());
}
catch(Exception e) {
// fall through
}
return false;
}
///////////////////////////////////////////
/////////////////// all private below
///////////////////////////////////////////
private String getAdminPortString(Server server, Config config) {
if (server == null || config == null)
return null;
try {
List<NetworkListener> listeners = config.getNetworkConfig().getNetworkListeners().getNetworkListener();
for (NetworkListener listener : listeners) {
if ("admin-listener".equals(listener.getProtocol()))
return translatePort(listener, server, config);
}
}
catch (Exception e) {
// handled below...
}
return null;
}
private String translatePort(NetworkListener adminListener, Server server, Config config) {
NetworkListener adminListenerRaw = null;
try {
Dom serverDom = Dom.unwrap(server);
Domain domain = serverDom.getHabitat().getComponent(Domain.class);
adminListenerRaw = GlassFishConfigBean.getRawView(adminListener);
String portString = adminListenerRaw.getPort();
if (!isToken(portString))
return portString;
PropertyResolver resolver = new PropertyResolver(domain, server.getName());
return resolver.getPropertyValue(portString);
}
catch (ClassCastException e) {
//jc: workaround for issue 12354
// TODO severe error
return translatePortOld(adminListener.getPort(), server, config);
}
}
private String translatePortOld(String portString, Server server, Config config) {
if (!isToken(portString))
return portString;
// isToken returned true so we are NOT assuming anything below!
String key = portString.substring(2, portString.length() - 1);
// check cluster and the cluster's config if applicable
// bnevins Jul 18, 2010 -- don't botehr this should never be called anymore
SystemProperty prop = server.getSystemProperty(key);
if (prop != null) {
return prop.getValue();
}
prop = config.getSystemProperty(key);
if (prop != null) {
return prop.getValue();
}
return null;
}
private static boolean isToken(String s) {
return s != null
&& s.startsWith("${")
&& s.endsWith("}")
&& s.length() > 3;
}
private final Server server;
private final Config config;
}