/* The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * http://www.sun.com/cddl/cddl.html or * install_dir/legal/LICENSE * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at install_dir/legal/LICENSE. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * Copyright 2005-2009 Sun Microsystems Inc. All Rights Reserved */ package com.sun.services; import com.sun.faban.common.Command; import com.sun.faban.common.CommandHandle; import com.sun.faban.common.NameValuePair; import com.sun.faban.harness.ConfigurationException; import com.sun.faban.harness.Configure; import com.sun.faban.harness.Context; import com.sun.faban.harness.RunContext; import com.sun.faban.harness.Start; import com.sun.faban.harness.Stop; import com.sun.faban.harness.services.ServiceContext; import java.rmi.RemoteException; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * This class implements the service to start/stop Memcached instances. * It can be used by any benchmark to manage memcached servers and * perform these operations remotely using this Service. * * @author Sheetal Patil based on work done by Shanti Subramanyam. */ public class MemcachedService { /** Injected service context. */ @Context public ServiceContext ctx; Logger logger = Logger.getLogger(MemcachedService.class.getName()); String memcachedCmdPath, myServers[]; List<NameValuePair<Integer>> myHostPorts; String memcachedStartCmd, memcachedBin, memcachedMemSize; private static final int DEFAULT_PORT = 11211; // default port CommandHandle memcacheHandles[]; /** * Configures this MemcachedService. */ @Configure public void configure() throws ConfigurationException { logger.fine("Configuring memcached service "); myHostPorts = ctx.getUniqueHostPorts(); if(myHostPorts == null){ throw new ConfigurationException("Memcached host:port is not provided"); } memcachedCmdPath = ctx.getProperty("cmdPath"); if(memcachedCmdPath != null && memcachedCmdPath.trim().length() > 0) { memcachedCmdPath = memcachedCmdPath + " "; }else{ throw new ConfigurationException("Memcached cmdPath is not provided"); } memcachedMemSize = ctx.getProperty("serverMemSize"); if(memcachedMemSize == null || memcachedMemSize.trim().length() <= 0){ throw new ConfigurationException("Memcached serverMemSize is not provided"); } memcachedStartCmd = memcachedCmdPath + " -u mysql -m " + memcachedMemSize; memcacheHandles = new CommandHandle[myHostPorts.size()]; logger.fine("MemcachedService Configure complete."); } /** * Starts the memcached instances. */ @Start public void startup() { int i = 0; for (NameValuePair<Integer> myHostPort : myHostPorts) { logger.fine("Starting memcached on " + myHostPort.name); Command startCmd; if (myHostPort.value != null) { startCmd = new Command(memcachedStartCmd + " -p " + myHostPort.value); } else { startCmd = new Command(memcachedStartCmd + " -p " + DEFAULT_PORT); } startCmd.setLogLevel(Command.STDOUT, Level.INFO); startCmd.setLogLevel(Command.STDERR, Level.INFO); logger.fine("Starting memcached with: " + memcachedStartCmd); startCmd.setSynchronous(false); // to run in bg try { // Run the command in the background memcacheHandles[i] = RunContext.exec(myHostPort.name, startCmd); logger.fine("Completed memcached server startup successfully on " + myHostPort.name); } catch (Exception e) { logger.log(Level.WARNING, "Failed to start memcached on " + myHostPort.name + '.', e); } ++i; } } /** * Stops the memcached instances. */ @Stop public void shutdown() { int i = 0; for (NameValuePair<Integer> myHostPort : myHostPorts) { if (memcacheHandles[i] != null) { try { int exit = memcacheHandles[i].exitValue(); logger.warning("Memcached on " + myHostPort.name + ':' + myHostPort.value + " has exited unexpectedly " + "during run with exit value of " + exit); } catch (IllegalThreadStateException ie) { // The server has not yet exited. Kill it try { memcacheHandles[i].destroy(); memcacheHandles[i] = null; } catch (RemoteException re) { logger.warning("Failed to stop memcached on " + myHostPort.name + ':' + myHostPort.value + " with " + re.toString()); logger.log(Level.FINE, "Exception", re); } } catch (RemoteException re) { logger.warning("exception while trying to get exitValue" + "on " + myHostPort.name + ':' + myHostPort.value + " - " + re.toString()); logger.log(Level.FINE, "Exception", re); } } ++i; } } }