/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.admin.internal; import org.apache.geode.admin.AdminException; import org.apache.geode.admin.ConfigurationParameter; import org.apache.geode.admin.ManagedEntityConfig; import org.apache.geode.internal.admin.GemFireVM; import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS; /** * A <code>SystemMember</code> that is also managed (or manageable) by the admin API. * * This class must be public so that its methods can be invoked reflectively (for MBean operations) * on instances of its subclasses. * * @since GemFire 4.0 */ public abstract class ManagedSystemMemberImpl extends SystemMemberImpl implements InternalManagedEntity { /** Controller for starting and stopping local or remote managers */ protected ManagedEntityController controller; /** The state of this managed entity (see bug 32455) */ private int state = UNKNOWN; /** A lock that is obtained while this entity's state changes */ private final Object stateChange = new Object(); ////////////////////// Constructors ////////////////////// /** * Creates a new <code>ManagedSystemMemberImpl</code> that represents an existing member of an * <code>AdminDistributedSystem</code>. */ protected ManagedSystemMemberImpl(AdminDistributedSystemImpl system, GemFireVM vm) throws AdminException { super(system, vm); this.controller = system.getEntityController(); } /** * Creates a new <code>ManagedSystemMemberImpl</code> that represents a non-existing member with * the given <code>ManagedEntityConfig</code> that has not yet been started. */ protected ManagedSystemMemberImpl(AdminDistributedSystemImpl system, ManagedEntityConfig config) throws AdminException { super(system); this.internalId = null; this.id = getNewId(); this.host = config.getHost(); this.name = this.id; this.controller = system.getEntityController(); } ////////////////////// Instance Methods ////////////////////// public String getWorkingDirectory() { return this.getEntityConfig().getWorkingDirectory(); } public void setWorkingDirectory(String workingDirectory) { this.getEntityConfig().setWorkingDirectory(workingDirectory); } public String getProductDirectory() { return this.getEntityConfig().getProductDirectory(); } public void setProductDirectory(String productDirectory) { this.getEntityConfig().setProductDirectory(productDirectory); } @Override public String getHost() { return this.getEntityConfig().getHost(); } public int setState(int state) { if (this.stateChange == null) { // The initial state is set in the constructor before // stateChange is initialized. int oldState = this.state; this.state = state; return oldState; } else { synchronized (this.stateChange) { int oldState = this.state; this.state = state; this.stateChange.notifyAll(); return oldState; } } } /** * Returns whether or not this managed system member needs to be stopped. If this member is * stopped or is stopping, then it does not need to be stopped. Otherwise, it will atomically * place this member in the {@link #STOPPING} state. See bug 32455. */ protected boolean needToStop() { synchronized (this.stateChange) { if (this.state == STOPPED || this.state == STOPPING) { return false; } else { setState(STOPPING); return true; } } } /** * Returns whether or not this managed system member needs to be started. If this member is * started or is starting, then it does not need to be started. Otherwise, it will atomically * place this member in the {@link #STARTING} state. See bug 32455. */ protected boolean needToStart() { synchronized (this.stateChange) { if (this.state == RUNNING || this.state == STARTING) { return false; } else { setState(STARTING); return true; } } } /** * Sets the state of this managed system member depending on whether or not <code>vm</code> is * <code>null</code>. */ @Override void setGemFireVM(GemFireVM vm) throws AdminException { super.setGemFireVM(vm); if (vm != null) { this.setState(RUNNING); } else { this.setState(STOPPED); } } /** * Waits until this system member's "state" is {@link #RUNNING}. */ public boolean waitToStart(long timeout) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < timeout) { synchronized (this.stateChange) { if (this.state == RUNNING) { break; } else { this.stateChange.wait(System.currentTimeMillis() - start); } } } synchronized (this.stateChange) { return this.state == RUNNING; } } /** * Waits until this system member's "state" is {@link #STOPPED}. */ public boolean waitToStop(long timeout) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < timeout) { synchronized (this.stateChange) { if (this.state == STOPPED) { break; } else { this.stateChange.wait(System.currentTimeMillis() - start); } } } synchronized (this.stateChange) { return this.state == STOPPED; } } /** * Appends configuration information to a <code>StringBuffer</code> that contains a command line. * Handles certain configuration parameters specially. */ protected void appendConfiguration(StringBuffer sb) { ConfigurationParameter[] params = this.getConfiguration(); for (int i = 0; i < params.length; i++) { ConfigurationParameter param = params[i]; if (!param.isModifiable()) { continue; } String name = param.getName(); String value = param.getValueAsString(); if (value != null && !value.equals("")) { if (name.equals(LOCATORS)) { // Use the new locator syntax so that is plays nicely with // rsh. See bug 32306. String locator = value; int firstBracket = locator.indexOf('['); int lastBracket = locator.indexOf(']'); if (firstBracket > -1 && lastBracket > -1) { String host = locator.substring(0, firstBracket); String port = locator.substring(firstBracket + 1, lastBracket); locator = host + ":" + port; } sb.append(" "); sb.append(name); sb.append("="); sb.append(locator); } else { sb.append(" "); sb.append(name); sb.append("="); sb.append(value); } } } } }