/** * 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) [2009-2011], VMware, 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.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.PostConstruct; import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.type.IntegerType; import org.hibernate.type.StringType; import org.hyperic.hq.appdef.Agent; import org.hyperic.hq.common.shared.ServerConfigManager; import org.hyperic.hq.dao.HibernateDAO; import org.hyperic.hq.product.Plugin; import org.hyperic.hq.product.server.session.PluginDAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.stereotype.Repository; @Repository public class AgentPluginStatusDAO extends HibernateDAO<AgentPluginStatus> { private static final String LIMIT_S_TO_CURRENT_AGENTS = "join EAM_AGENT agent on s.agent_id = agent.id " + "where agent.version >= :serverVersion "; private static final String SYNCHABLE_AGENT_IDS_QUERY_STRING = "select distinct agent_id from EAM_AGENT_PLUGIN_STATUS s "+ LIMIT_S_TO_CURRENT_AGENTS + "and exists (select 1 from EAM_PLATFORM p where p.agent_id = s.agent_id)"; private static final String CUR_UNSYNCHABLE_AGENT_IDS_QUERY_STRING = "select distinct id from EAM_AGENT where version >= :serverVersion and " + " id not in (" + SYNCHABLE_AGENT_IDS_QUERY_STRING + ") "; private final AgentDAO agentDAO; private final PluginDAO pluginDAO; private final ServerConfigManager serverConfigManager; @Autowired public AgentPluginStatusDAO(SessionFactory factory, AgentDAO agentDAO, PluginDAO pluginDAO, ServerConfigManager serverConfigManager) { super(AgentPluginStatus.class, factory); this.agentDAO = agentDAO; this.pluginDAO = pluginDAO; this.serverConfigManager = serverConfigManager; } @PostConstruct public void initCache() { new HibernateTemplate(sessionFactory, true).execute(new HibernateCallback<Object>() { public Object doInHibernate(Session session) throws HibernateException, SQLException { session.createQuery("from AgentPluginStatus").list(); return null; } }); } public void saveOrUpdate(AgentPluginStatus agentPluginStatus) { save(agentPluginStatus); } /** * @return {@link Map} of {@link String} of the jar-name to {@link AgentPluginStatus} */ @SuppressWarnings("unchecked") public Map<String, AgentPluginStatus> getPluginStatusByAgent(Agent agent) { final List<AgentPluginStatus> list = getSession().createQuery("from AgentPluginStatus where agent = :agent") .setParameter("agent", agent) .list(); final Map<String, AgentPluginStatus> rtn = new HashMap<String, AgentPluginStatus>(list.size()); for (final AgentPluginStatus status : list) { rtn.put(status.getFileName(), status); } return rtn; } public Map<Plugin, Collection<AgentPluginStatus>> getOutOfSyncAgentsByPlugin() { final Map<Plugin, Collection<AgentPluginStatus>> rtn = new HashMap<Plugin, Collection<AgentPluginStatus>>(); final List<Integer> list = getOutOfSyncPlugins(null); for (final Integer id : list) { final AgentPluginStatus st = get(id); final String pluginName = st.getPluginName(); final Plugin plugin = pluginDAO.findByName(pluginName); Collection<AgentPluginStatus> tmp; if (null == (tmp = rtn.get(plugin))) { tmp = new ArrayList<AgentPluginStatus>(); rtn.put(plugin, tmp); } tmp.add(st); } return rtn; } Map<Agent, Collection<AgentPluginStatus>> getOutOfSyncPluginsByAgent() { final Map<Agent, Collection<AgentPluginStatus>> rtn = new HashMap<Agent, Collection<AgentPluginStatus>>(); final List<Integer> list = getOutOfSyncPlugins(null); for (final Integer id : list) { final AgentPluginStatus st = get(id); final int agentId = st.getAgent().getId(); final Agent agent = agentDAO.get(agentId); Collection<AgentPluginStatus> tmp; if (null == (tmp = rtn.get(agent))) { tmp = new ArrayList<AgentPluginStatus>(); rtn.put(agent, tmp); } tmp.add(st); } return rtn; } public List<String> getOutOfSyncPluginNamesByAgentId(int agentId) { final List<Integer> ids = getOutOfSyncPlugins(agentId); final List<String> rtn = new ArrayList<String>(ids.size()); for (final Integer id : ids) { final AgentPluginStatus st = get(id); final String pluginName = st.getPluginName(); rtn.add(pluginName); } return rtn; } /** * Get our of sync plugins for agents, whose version is not older than that of * the server. * @param agentId may be null * @return {@link List} of {@link Integer} which represents the AgentPluginStatusId */ @SuppressWarnings("unchecked") private List<Integer> getOutOfSyncPlugins(Integer agentId) { String serverMajorVersion = serverConfigManager.getServerMajorVersion(); final String agentSql = agentId == null ? "" : " s.agent_id = :agentId AND "; final String sql = new StringBuilder(256) .append("select distinct s.id ") .append("from EAM_AGENT_PLUGIN_STATUS s ") .append(LIMIT_S_TO_CURRENT_AGENTS) .append(" AND (") .append(agentSql) .append("not exists ( ") .append(" select 1 ") .append(" from EAM_PLUGIN p ") .append(" join EAM_AGENT_PLUGIN_STATUS st on p.md5 = st.md5 ") .append(" where st.agent_id = s.agent_id and s.md5 = st.md5 ") .append(" and p.deleted = '0'") .append(") ") .append("OR s.last_sync_status != :syncSuccess)") .toString(); final SQLQuery query = getSession().createSQLQuery(sql); if (agentId != null) { query.setParameter("agentId", agentId); } query.setParameter("serverVersion", serverMajorVersion); return query.addScalar("id", Hibernate.INTEGER) .setParameter("syncSuccess", AgentPluginStatusEnum.SYNC_SUCCESS.toString()) .list(); } /** * @return {@link Collection} of {@link Object[]} where [0] = agentId and [1] = pluginName */ @SuppressWarnings("unchecked") Collection<Object[]> getPluginsNotOnAllAgents() { final String sql = new StringBuilder(256) .append("SELECT distinct a.id,p.name from EAM_PLUGIN p, EAM_AGENT a ") .append("JOIN EAM_PLATFORM pl on pl.agent_id = a.id ") .append("WHERE not exists ( ") .append(" SELECT 1 FROM EAM_AGENT_PLUGIN_STATUS s ") .append(" WHERE a.id = s.agent_id and s.plugin_name = p.name ") .append(") and p.deleted = '0'") .toString(); return getSession().createSQLQuery(sql) .addScalar("id", Hibernate.INTEGER) .addScalar("name", Hibernate.STRING) .list(); } @SuppressWarnings("unchecked") Collection<Integer> getPluginsNotOnAgent(int agentId) { final String sql = new StringBuilder(128) .append("select p.id ") .append("from EAM_PLUGIN p ") .append("where not exists (") .append(" select 1 from EAM_AGENT_PLUGIN_STATUS ") .append(" where agent_id = :agentId and plugin_name = p.name") .append(") and p.deleted = '0'") .toString(); return getSession().createSQLQuery(sql) .addScalar("id", Hibernate.INTEGER) .setParameter("agentId", agentId) .list(); } public Map<String, AgentPluginStatus> getStatusByAgentId(Integer agentId) { final String hql = "from AgentPluginStatus where agent.id = :agentId"; @SuppressWarnings("unchecked") final Collection<AgentPluginStatus> list = getSession().createQuery(hql) .setParameter("agentId", agentId) .list(); final Map<String, AgentPluginStatus> rtn = new HashMap<String, AgentPluginStatus>(list.size()); for (final AgentPluginStatus status : list) { rtn.put(status.getPluginName(), status); } return rtn; } public Map<Integer, Map<String, AgentPluginStatus>> getStatusByAgentIds(Collection<Integer> agentIds) { if (agentIds == null || agentIds.isEmpty()) { return Collections.emptyMap(); } final String hql = "from AgentPluginStatus where agent.id in (:agentIds)"; @SuppressWarnings("unchecked") final Collection<AgentPluginStatus> list = getSession().createQuery(hql) .setParameterList("agentIds", agentIds, new IntegerType()) .list(); final Map<Integer, Map<String, AgentPluginStatus>> rtn = new HashMap<Integer, Map<String, AgentPluginStatus>>(list.size()); for (final AgentPluginStatus status : list) { final Integer agentId = status.getAgent().getId(); Map<String, AgentPluginStatus> map = rtn.get(status.getAgent().getId()); if (map == null) { map = new HashMap<String, AgentPluginStatus>(); rtn.put(agentId, map); } map.put(status.getPluginName(), status); } return rtn; } @SuppressWarnings("unchecked") public Collection<AgentPluginStatus> getPluginStatusByFileName(String fileName, Collection<AgentPluginStatusEnum> statuses) { final String hql = new StringBuilder(128) .append("from AgentPluginStatus s ") .append("where s.fileName = :fileName and s.lastSyncStatus in (:statuses) ") .append("and exists (select 1 from Platform p where p.agent.id = s.agent.id)") .toString(); Collection<String> vals = new ArrayList<String>(statuses.size()); for (final AgentPluginStatusEnum s : statuses) { vals.add(s.toString()); } return getSession().createQuery(hql) .setParameter("fileName", fileName) .setParameterList("statuses", vals, new StringType()) .list(); } @SuppressWarnings("unchecked") public Set<Integer> getAutoUpdatingAgentIDs() { String serverMajorVersion = serverConfigManager.getServerMajorVersion(); final SQLQuery query = getSession().createSQLQuery(SYNCHABLE_AGENT_IDS_QUERY_STRING); query.setParameter("serverVersion", serverMajorVersion); final List<Integer> ids = query.addScalar("agent_id", Hibernate.INTEGER).list(); final Set<Integer> idsSet = new HashSet<Integer>(ids); return idsSet; } @SuppressWarnings("unchecked") public Collection<Agent> getAutoUpdatingAgents() { final Set<Integer> idsSet = getAutoUpdatingAgentIDs(); final List<Agent> rtn = new ArrayList<Agent>(idsSet.size()); for (final Integer agentId : idsSet) { rtn.add(agentDAO.findById(agentId)); } return rtn; } @SuppressWarnings("unchecked") public List<Agent> getCurrentNonSyncAgents() { String serverMajorVersion = serverConfigManager.getServerMajorVersion(); final SQLQuery query = getSession().createSQLQuery(CUR_UNSYNCHABLE_AGENT_IDS_QUERY_STRING); query.setParameter("serverVersion", serverMajorVersion); final List<Integer> ids = query.addScalar("id", Hibernate.INTEGER).list(); final Set<Integer> idsSet = new HashSet<Integer>(ids); final List<Agent> rtn = new ArrayList<Agent>(idsSet.size()); for (final Integer agentId : idsSet) { rtn.add(agentDAO.findById(agentId)); } return rtn; } public Long getNumAutoUpdatingAgents() { Set<Integer> synchedAgentIDs = getAutoUpdatingAgentIDs(); return ((long)synchedAgentIDs.size()); } /* @SuppressWarnings("unchecked") public Collection<Agent> getAutoUpdatingAgents() { String serverMajorVersion = serverConfigManager.getServerMajorVersion(); final String hql = new StringBuilder(150) .append("select distinct agent_id from EAM_AGENT_PLUGIN_STATUS s ") .append(LIMIT_S_TO_CURRENT_AGENTS) .append("and exists (select 1 from EAM_PLATFORM p where p.agent_id = s.agent_id)") .toString(); final SQLQuery query = getSession().createSQLQuery(hql); query.setParameter("serverVersion", serverMajorVersion); final List<Integer> ids = query.addScalar("agent_id", Hibernate.INTEGER).list(); final List<Agent> rtn = new ArrayList<Agent>(ids.size()); for (final Integer agentId : ids) { rtn.add(agentDAO.findById(agentId)); } return rtn; } */ public void removeAgentPluginStatuses(Integer agentId, Collection<String> pluginFileNames) { final String hql = "select id from AgentPluginStatus where agent.id = :agentId and fileName in (:filenames)"; @SuppressWarnings("unchecked") final List<Integer> list = getSession().createQuery(hql) .setParameter("agentId", agentId, new IntegerType()) .setParameterList("filenames", pluginFileNames) .list(); for (final Integer sapsId : list) { AgentPluginStatus status = get(sapsId); if (status == null) { continue; } remove(status); } } public Map<Agent, Collection<AgentPluginStatus>> getPluginsToRemoveFromAgents() { final String hql = new StringBuilder(64) .append("select s.id FROM EAM_AGENT_PLUGIN_STATUS s ") .append("where not exists (") .append("select 1 from EAM_PLUGIN p where p.name = s.plugin_name and p.deleted = '0')") .toString(); @SuppressWarnings("unchecked") final List<Integer> list = getSession().createSQLQuery(hql) .addScalar("id", Hibernate.INTEGER) .list(); if (list.isEmpty()) { return Collections.emptyMap(); } final Map<Agent, Collection<AgentPluginStatus>> rtn = new HashMap<Agent, Collection<AgentPluginStatus>>(list.size()); for (final Integer sapsId : list) { final AgentPluginStatus status = get(sapsId); if (status == null) { continue; } final Agent agent = status.getAgent(); if (agent == null) { continue; } Collection<AgentPluginStatus> tmp = rtn.get(agent); if (tmp == null) { tmp = new ArrayList<AgentPluginStatus>(); rtn.put(agent, tmp); } tmp.add(status); } return rtn; } @SuppressWarnings("unchecked") public Collection<AgentPluginStatus> getStatusByAgentAndFileNames(Integer agentId, Collection<String> fileNames) { final String hql = "from AgentPluginStatus where agent.id = :agentId AND fileName in (:fileNames)"; return getSession().createQuery(hql) .setParameterList("fileNames", fileNames) .setInteger("agentId", agentId) .list(); } public Map<Agent, AgentPluginStatus> getPluginStatusByFileName(String fileName) { final String hql = "select id from AgentPluginStatus where fileName = :fileName"; @SuppressWarnings("unchecked") final List<Integer> list = getSession().createQuery(hql).setParameter("fileName", fileName).list(); final Map<Agent, AgentPluginStatus> rtn = new HashMap<Agent, AgentPluginStatus>(list.size()); for (final Integer sapsId : list) { final AgentPluginStatus status = get(sapsId); if (status == null) { continue; } final Agent agent = status.getAgent(); if (agent == null) { continue; } rtn.put(agent, status); } return rtn; } public Map<String, Long> getFileNameCounts(Collection<String> pluginFileNames) { if (pluginFileNames != null && pluginFileNames.isEmpty()) { return Collections.emptyMap(); } String and = ""; if (pluginFileNames != null) { and = "and s.fileName in (:filenames) "; } final String hql = new StringBuilder(256) .append("select s.fileName, count(*) from AgentPluginStatus s ") .append("where exists (") .append("select 1 from Agent a ") .append("join a.platforms p ") .append("where a.id = s.agent.id) ") .append(and) .append("group by s.fileName") .toString(); final Query query = getSession().createQuery(hql); if (pluginFileNames != null) { query.setParameterList("filenames", pluginFileNames); } @SuppressWarnings("unchecked") final List<Object[]> list = query.list(); final Map<String, Long> rtn = new HashMap<String, Long>(list.size()); for (final Object[] obj : list) { rtn.put((String) obj[0], ((Number) obj[1]).longValue()); } return rtn; } public Map<String, Long> getFileNameCounts() { return getFileNameCounts(null); } @SuppressWarnings("unchecked") public Collection<Plugin> getOrphanedPlugins() { final String hql = new StringBuilder(200) .append("from Plugin p where deleted = '1' and not exists (") .append(" select 1 from AgentPluginStatus s") .append(" join s.agent a") .append(" join a.platforms pl") .append(" where s.fileName = p.path") .append(")") .toString(); return getSession().createQuery(hql).list(); } @SuppressWarnings("unchecked") public List<AgentPluginStatus> getPluginStatusByAgent(AgentPluginStatusEnum ... keys) { final List<String> vals = new ArrayList<String>(keys.length); for (AgentPluginStatusEnum key : keys) { vals.add(key.toString()); } final String hql = new StringBuilder(128) .append("from AgentPluginStatus s ") .append("where exists (select 1 from Platform p where p.agent.id = s.agent.id) ") .append("and s.lastSyncStatus in (:statuses)") .toString(); return getSession() .createQuery(hql) .setParameterList("statuses", vals, new StringType()) .list(); } @SuppressWarnings("unchecked") public List<Integer> getAllIds() { final String hql = "select id from AgentPluginStatus"; return getSession().createQuery(hql).list(); } }