From: <pn...@hy...> - 2009-12-08 23:21:19
|
Author: pnguyen Date: 2009-12-08 15:21:04 -0800 (Tue, 08 Dec 2009) New Revision: 14056 URL: http://svn.hyperic.org/?view=rev&root=Hyperic+HQ&revision=14056 Added: trunk/src/org/hyperic/hq/appdef/server/session/AsyncDeleteAgentCache.java Modified: trunk/src/org/hyperic/hq/bizapp/server/session/AppdefBossEJBImpl.java trunk/src/org/hyperic/hq/measurement/server/session/MeasurementManagerEJBImpl.java trunk/src/org/hyperic/hq/measurement/server/session/MeasurementProcessorEJBImpl.java Log: [HHQ-3584, HHQ-3585] Disable the measurements for the "root" resource (the resource that was selected by the user); Temporarily cache the "lost" agent information so that this information can be used during the asynchronous delete process to unschedule metrics. These changes may be refactored later in HHQ-3598. Added: trunk/src/org/hyperic/hq/appdef/server/session/AsyncDeleteAgentCache.java =================================================================== --- trunk/src/org/hyperic/hq/appdef/server/session/AsyncDeleteAgentCache.java (rev 0) +++ trunk/src/org/hyperic/hq/appdef/server/session/AsyncDeleteAgentCache.java 2009-12-08 23:21:04 UTC (rev 14056) @@ -0,0 +1,92 @@ +/* + * NOTE: This copyright does *not* cover user programs that use HQ + * program services by normal system calls through the application + * program interfaces provided as part of the Hyperic Plug-in Development + * Kit or the Hyperic Client Development Kit - this is merely considered + * normal use of the program, and does *not* fall under the heading of + * "derived work". + * + * Copyright (C) [2004-2009], Hyperic, Inc. + * This file is part of HQ. + * + * HQ is free software; you can redistribute it and/or modify + * it under the terms version 2 of the GNU General Public License as + * published by the Free Software Foundation. This program is distributed + * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + */ + +package org.hyperic.hq.appdef.server.session; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.hyperic.hq.appdef.shared.AppdefEntityID; + +/** + * This class is used during the aynchronous delete process + * to unschedule metrics. It is an in-memory map of resources + * and its agent because that info no longer exists in the DB. + */ +public class AsyncDeleteAgentCache { + private Log log = LogFactory.getLog(AsyncDeleteAgentCache.class); + + private final Map _cache; + + private static final AsyncDeleteAgentCache singleton = + new AsyncDeleteAgentCache(); + + private AsyncDeleteAgentCache() { + _cache = Collections.synchronizedMap(new HashMap()); + } + + /** + * + * @param key The AppdefEntityID of the async deleted resource + * @return Integer The agentId of the async deleted resource + */ + public Integer get(AppdefEntityID key) { + return (Integer) _cache.get(key); + } + + /** + * + * @param key The AppdefEntityID of the async deleted resource + * @param Integer The agentId of the async deleted resource + */ + public void put(AppdefEntityID key, Integer value) { + _cache.put(key, value); + } + + public void remove(AppdefEntityID key) { + _cache.remove(key); + } + + public void clear() { + _cache.clear(); + } + + public int getSize() { + return _cache.size(); + } + + public String toString() { + return _cache.toString(); + } + + public static AsyncDeleteAgentCache getInstance() { + return singleton; + } + +} Modified: trunk/src/org/hyperic/hq/bizapp/server/session/AppdefBossEJBImpl.java =================================================================== --- trunk/src/org/hyperic/hq/bizapp/server/session/AppdefBossEJBImpl.java 2009-12-08 23:08:55 UTC (rev 14055) +++ trunk/src/org/hyperic/hq/bizapp/server/session/AppdefBossEJBImpl.java 2009-12-08 23:21:04 UTC (rev 14056) @@ -58,6 +58,7 @@ import org.hyperic.hq.appdef.server.session.AppdefResourceType; import org.hyperic.hq.appdef.server.session.Application; import org.hyperic.hq.appdef.server.session.ApplicationType; +import org.hyperic.hq.appdef.server.session.AsyncDeleteAgentCache; import org.hyperic.hq.appdef.server.session.CPropResource; import org.hyperic.hq.appdef.server.session.CPropResourceSortField; import org.hyperic.hq.appdef.server.session.Cprop; @@ -1345,7 +1346,7 @@ switch (aeid.getType()) { case AppdefEntityConstants.APPDEF_TYPE_SERVER : final ServerManagerLocal sMan = getServerManager(); - sMan.removeServer(subject, sMan.findServerById(id)); + removeServer(subject, sMan.findServerById(id)); break; case AppdefEntityConstants.APPDEF_TYPE_PLATFORM: final PlatformManagerLocal pMan = getPlatformManager(); @@ -1353,7 +1354,7 @@ break; case AppdefEntityConstants.APPDEF_TYPE_SERVICE : final ServiceManagerLocal svcMan = getServiceManager(); - svcMan.removeService(subject, svcMan.findServiceById(id)); + removeService(subject, svcMan.findServiceById(id)); break; case AppdefEntityConstants.APPDEF_TYPE_GROUP: final ResourceGroupManagerLocal rgMan = @@ -1392,9 +1393,15 @@ */ public void removeDeletedResources() throws ApplicationException, VetoException, RemoveException { + final boolean debug = log.isDebugEnabled(); final StopWatch watch = new StopWatch(); final AuthzSubject subject = getAuthzSubjectManager().findSubjectById(AuthzConstants.overlordId); + + AsyncDeleteAgentCache cache = AsyncDeleteAgentCache.getInstance(); + if (debug) { + log.debug("AsyncDeleteAgentCache start size=" + cache.getSize()); + } watch.markTimeBegin("removeApplications"); Collection applications = @@ -1408,7 +1415,7 @@ } } watch.markTimeEnd("removeApplications"); - if (log.isDebugEnabled()) { + if (debug) { log.debug("Removed " + applications.size() + " applications"); } @@ -1422,19 +1429,36 @@ } } watch.markTimeEnd("removeResourceGroups"); - if (log.isDebugEnabled()) { + if (debug) { log.debug("Removed " + groups.size() + " resource groups"); } // Look through services, servers, platforms, applications, and groups + watch.markTimeBegin("removeServices"); Collection services = getServiceManager().findDeletedServices(); removeServices(subject, services); + watch.markTimeEnd("removeServices"); + watch.markTimeBegin("removeServers"); Collection servers = getServerManager().findDeletedServers(); removeServers(subject, servers); + watch.markTimeEnd("removeServers"); watch.markTimeBegin("removePlatforms"); Collection platforms = getPlatformManager().findDeletedPlatforms(); + removePlatforms(subject, platforms); + watch.markTimeEnd("removePlatforms"); + + if (debug) { + log.debug("removeDeletedResources: " + watch); + log.debug("AsyncDeleteAgentCache end size=" + cache.getSize()); + if (cache.getSize() > 0) { + log.debug("AsyncDeleteAgentCache " + cache); + } + } + } + + private final void removePlatforms(AuthzSubject subject, Collection platforms) { for (final Iterator it = platforms.iterator(); it.hasNext(); ) { final Platform platform = (Platform)it.next(); try { @@ -1444,11 +1468,9 @@ log.error("Unable to remove platform: " + e, e); } } - watch.markTimeEnd("removePlatforms"); if (log.isDebugEnabled()) { log.debug("Removed " + platforms.size() + " platforms"); - log.debug("removeDeletedResources() timing: " + watch); - } + } } private final void removeServers(AuthzSubject subject, Collection servers) { @@ -1471,7 +1493,7 @@ } watch.markTimeEnd("removeServers"); if (log.isDebugEnabled()) { - log.debug("Removed " + servers.size() + " services"); + log.debug("Removed " + servers.size() + " servers: " + watch); } } @@ -1494,21 +1516,11 @@ } watch.markTimeEnd("removeServices"); if (log.isDebugEnabled()) { - log.debug("Removed " + services.size() + " services"); + log.debug("Removed " + services.size() + " services: " + watch); } } /** - * Disable all measurements for a resource - * @param id the resource's ID - */ - private void disableMeasurements(AuthzSubject subject, Resource res) - throws PermissionException - { - getMetricManager().disableMeasurements(subject, res); - } - - /** * Remove config and track plugins for a given resource */ private void removeTrackers(AuthzSubject subject, AppdefEntityID id) @@ -1553,14 +1565,27 @@ public void removePlatform(AuthzSubject subject, Platform platform) throws ApplicationException, VetoException { + boolean debug = log.isDebugEnabled(); + StopWatch watch = new StopWatch(); + try { + // Update cache for asynchronous delete process + if (debug) watch.markTimeBegin("buildAsyncDeleteAgentCache"); + buildAsyncDeleteAgentCache(platform); + if (debug) watch.markTimeEnd("buildAsyncDeleteAgentCache"); + // Disable all measurements for this platform. We don't actually // remove the measurements here to avoid delays in deleting // resources. - disableMeasurements(subject, platform.getResource()); - + if (debug) watch.markTimeBegin("disableMeasurements"); + getMetricManager().disableMeasurements( + subject, platform.getResource(), true); + if (debug) watch.markTimeEnd("disableMeasurements"); + // Remove from AI queue try { + if (debug) watch.markTimeBegin("removeFromAIQ"); + List aiplatformList = new ArrayList(); Integer platformID = platform.getId(); final AIQueueManagerLocal aiMan = getAIManager(); @@ -1573,6 +1598,7 @@ aiMan.processQueue(subject, aiplatformList, null, null, AIQueueConstants.Q_DECISION_PURGE); } + if (debug) watch.markTimeEnd("removeFromAIQ"); } catch (AIQApprovalException e) { log.error("Error removing from AI queue", e); } catch (FinderException e) { @@ -1580,7 +1606,9 @@ } // now, remove the platform. + if (debug) watch.markTimeBegin("removePlatform"); getPlatformManager().removePlatform(subject, platform); + if (debug) watch.markTimeEnd("removePlatform"); } catch (RemoveException e) { log.error("Caught EJB RemoveException",e); throw new SystemException(e); @@ -1588,18 +1616,36 @@ log.error("Caught PermissionException while removing platform: " + platform.getId(),e); throw e; + } finally { + if (debug) { + log.debug("removePlatform[id=" + platform.getId() + "]: " + watch); + } } } private void removeServer(AuthzSubject subject, Server server) - throws PermissionException, - VetoException { + throws PermissionException, VetoException + { + boolean debug = log.isDebugEnabled(); + StopWatch watch = new StopWatch(); + try { + // Update cache for asynchronous delete process + if (debug) watch.markTimeBegin("buildAsyncDeleteAgentCache"); + buildAsyncDeleteAgentCache(server); + if (debug) watch.markTimeEnd("buildAsyncDeleteAgentCache"); + // now remove the measurements - disableMeasurements(subject, server.getResource()); + if (debug) watch.markTimeBegin("disableMeasurements"); + getMetricManager().disableMeasurements( + subject, server.getResource(), true); + if (debug) watch.markTimeEnd("disableMeasurements"); + try { + if (debug) watch.markTimeBegin("toggleRuntimeScan"); getAutoInventoryManager().toggleRuntimeScan( getOverlord(), server.getEntityId(), false); + if (debug) watch.markTimeEnd("toggleRuntimeScan"); } catch (ResourceDeletedException e) { log.debug(e); } catch (AutoinventoryException e) { @@ -1609,8 +1655,11 @@ log.error("Unexpected error turning off RuntimeScan for: " + server + " (handled gracefully).", e); } + // finally, remove the server + if (debug) watch.markTimeBegin("removeServer"); getServerManager().removeServer(subject, server); + if (debug) watch.markTimeEnd("removeServer"); } catch (RemoveException e) { rollback(); throw new SystemException(e); @@ -1619,10 +1668,68 @@ log.error("Caught permission exception: [server:" + server.getId() + "]"); throw (PermissionException) e; + } finally { + if (debug) { + log.debug("removeServer[id=" + server.getId() + "]: " + watch); + } } } + + private void buildAsyncDeleteAgentCache(Server server) { + AsyncDeleteAgentCache cache = AsyncDeleteAgentCache.getInstance(); + + try { + Agent agent = findResourceAgent(server.getEntityId()); + + for (Iterator i=server.getServices().iterator(); i.hasNext(); ) { + Service s = (Service)i.next(); + AppdefEntityID eid = s.getEntityId(); + cache.put(eid, agent.getId()); + } + } catch (AgentNotFoundException anfe) { + if (cache.get(server.getEntityId()) == null) { + if (!server.getServerType().isVirtual()) { + log.warn("Unable to build AsyncDeleteAgentCache for server[id=" + + server.getId() + + ", name=" + server.getName() + "]: " + + anfe.getMessage()); + } + } else { + log.debug("Platform has been asynchronously deleted: " + + anfe.getMessage()); + } + } catch (Exception e) { + log.warn("Unable to build AsyncDeleteAgentCache for server[id=" + + server.getId() + + ", name=" + server.getName() + "]: " + + e.getMessage()); + } + } + private void buildAsyncDeleteAgentCache(Platform platform) { + AsyncDeleteAgentCache cache = AsyncDeleteAgentCache.getInstance(); + + try { + Agent agent = platform.getAgent(); + + for (Iterator i=platform.getServers().iterator(); i.hasNext(); ) { + Server s = (Server)i.next(); + if (!s.getServerType().isVirtual()) { + AppdefEntityID eid = s.getEntityId(); + cache.put(eid, agent.getId()); + } + buildAsyncDeleteAgentCache(s); + } + } catch (Exception e) { + log.warn("Unable to build AsyncDeleteAgentCache for platform[id=" + + platform.getId() + + ", name=" + platform.getName() + "]: " + + e.getMessage()); } + } + /** + * Used only during the asynchronous delete process. + * * @ejb:transaction type="RequiresNew" * @ejb:interface-method */ @@ -1632,16 +1739,13 @@ removeServer(subject, server); } - /** - * @ejb:transaction type="RequiresNew" - * @ejb:interface-method - */ - public void _removeServiceInNewTran(AuthzSubject subject, Service service) + private void removeService(AuthzSubject subject, Service service) throws VetoException, PermissionException, RemoveException { try { // now remove any measurements associated with the service - disableMeasurements(subject, service.getResource()); + getMetricManager().disableMeasurements( + subject, service.getResource(), true); removeTrackers(subject, service.getEntityId()); getServiceManager().removeService(subject, service); } catch (PermissionException e) { @@ -1652,6 +1756,18 @@ throw (RemoveException) e; } } + + /** + * Used only during the asynchronous delete process. + * + * @ejb:transaction type="RequiresNew" + * @ejb:interface-method + */ + public void _removeServiceInNewTran(AuthzSubject subject, Service service) + throws VetoException, PermissionException, RemoveException + { + removeService(subject, service); + } /** * @ejb:transaction type="RequiresNew" @@ -3999,7 +4115,11 @@ } /** @ejb:create-method */ - public void ejbCreate() throws CreateException {} + public void ejbCreate() throws CreateException { + if (log.isDebugEnabled()) { + log.debug("ejbCreate called on " + this); + } + } public void ejbRemove() {} public void ejbActivate() {} Modified: trunk/src/org/hyperic/hq/measurement/server/session/MeasurementManagerEJBImpl.java =================================================================== --- trunk/src/org/hyperic/hq/measurement/server/session/MeasurementManagerEJBImpl.java 2009-12-08 23:08:55 UTC (rev 14055) +++ trunk/src/org/hyperic/hq/measurement/server/session/MeasurementManagerEJBImpl.java 2009-12-08 23:21:04 UTC (rev 14056) @@ -1183,12 +1183,42 @@ * * @ejb:interface-method */ - public void disableMeasurements(AuthzSubject subject, Resource res) - throws PermissionException { - List mcol = getMeasurementDAO().findEnabledByResource(res); + public void disableMeasurements(AuthzSubject subject, Resource res) + throws PermissionException + { + disableMeasurements(subject, res, false); + } + + /** + * Disable all Measurements for a resource + * + * @ejb:interface-method + */ + public void disableMeasurements(AuthzSubject subject, + Resource res, + boolean isAsyncDelete) + throws PermissionException + { + List mcol = null; - if (mcol.size() == 0) + if (isAsyncDelete) { + // For asynchronous deletes, we need to get all measurements + // because some disabled measurements are not unscheduled + // from the agent (like during the maintenance window) and + // we need to unschedule these measurements + mcol = findMeasurements(subject, res); + } else { + mcol = getMeasurementDAO().findEnabledByResource(res); + } + + if (mcol.size() == 0) { + if (log.isDebugEnabled()) { + log.debug("No measurements to disable for resourceId=" + + res.getId() + + ", isAsyncDelete=" + isAsyncDelete); + } return; + } Integer[] mids = new Integer[mcol.size()]; Iterator it = mcol.iterator(); Modified: trunk/src/org/hyperic/hq/measurement/server/session/MeasurementProcessorEJBImpl.java =================================================================== --- trunk/src/org/hyperic/hq/measurement/server/session/MeasurementProcessorEJBImpl.java 2009-12-08 23:08:55 UTC (rev 14055) +++ trunk/src/org/hyperic/hq/measurement/server/session/MeasurementProcessorEJBImpl.java 2009-12-08 23:21:04 UTC (rev 14056) @@ -6,7 +6,7 @@ * normal use of the program, and does *not* fall under the heading of * "derived work". * - * Copyright (C) [2004-2008], Hyperic, Inc. + * Copyright (C) [2004-2009], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify @@ -41,6 +41,7 @@ import org.hyperic.hq.agent.AgentRemoteException; import org.hyperic.hq.appdef.Agent; import org.hyperic.hq.appdef.server.session.AgentManagerEJBImpl; +import org.hyperic.hq.appdef.server.session.AsyncDeleteAgentCache; import org.hyperic.hq.appdef.shared.AgentManagerLocal; import org.hyperic.hq.appdef.shared.AgentNotFoundException; import org.hyperic.hq.appdef.shared.AppdefEntityID; @@ -118,20 +119,33 @@ */ private Map getAgentMap(List aeids) { AgentManagerLocal aMan = AgentManagerEJBImpl.getOne(); + AsyncDeleteAgentCache cache = AsyncDeleteAgentCache.getInstance(); Map rtn = new HashMap(aeids.size()); List tmp; for (Iterator it=aeids.iterator(); it.hasNext(); ) { AppdefEntityID eid = (AppdefEntityID)it.next(); - Integer agentId; + Integer agentId = null; try { agentId = aMan.getAgent(eid).getId(); + } catch (AgentNotFoundException e) { + // HHQ-3585: It may be in an asynchronous + // delete state, so check the cache + agentId = cache.get(eid); + + if (agentId == null) { + log.warn(e.getMessage()); + } else { + // No longer needed, remove from cache + cache.remove(eid); + } + } + + if (agentId != null) { if (null == (tmp = (List)rtn.get(agentId))) { tmp = new ArrayList(); rtn.put(agentId, tmp); } tmp.add(eid); - } catch (AgentNotFoundException e) { - log.warn(e.getMessage()); } } return rtn; |