package com.taobao.zeus.store.mysql; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import com.taobao.zeus.client.ZeusException; import com.taobao.zeus.model.GroupDescriptor; import com.taobao.zeus.model.JobDescriptorOld; import com.taobao.zeus.model.JobDescriptorOld.JobRunTypeOld; import com.taobao.zeus.model.JobDescriptorOld.JobScheduleTypeOld; import com.taobao.zeus.model.JobStatus; import com.taobao.zeus.model.processer.DownloadProcesser; import com.taobao.zeus.model.processer.Processer; import com.taobao.zeus.store.GroupBeanOld; import com.taobao.zeus.store.GroupManagerOld; import com.taobao.zeus.store.GroupManagerToolOld; import com.taobao.zeus.store.JobBeanOld; import com.taobao.zeus.store.mysql.persistence.GroupPersistence; import com.taobao.zeus.store.mysql.persistence.JobPersistence; import com.taobao.zeus.store.mysql.persistence.JobPersistenceOld; import com.taobao.zeus.store.mysql.persistence.Worker; import com.taobao.zeus.store.mysql.persistence.ZeusUser; import com.taobao.zeus.store.mysql.tool.GroupValidate; import com.taobao.zeus.store.mysql.tool.JobValidateOld; import com.taobao.zeus.store.mysql.tool.PersistenceAndBeanConvertOld; import com.taobao.zeus.util.Tuple; @SuppressWarnings("unchecked") public class MysqlGroupManagerOld extends HibernateDaoSupport implements GroupManagerOld { @Override public void deleteGroup(String user, String groupId) throws ZeusException { GroupBeanOld group = getDownstreamGroupBean(groupId); if (group.isDirectory()) { // if (!group.getChildrenGroupBeans().isEmpty()) { // throw new ZeusException("该组下不为空,无法删除"); // } boolean candelete = true; for (GroupBeanOld child : group.getChildrenGroupBeans()) { if (child.isExisted()) { candelete = false; break; } } if (!candelete) { throw new ZeusException("该组下不为空,无法删除"); } } else { if (!group.getJobBeans().isEmpty()) { throw new ZeusException("该组下不为空,无法删除"); } } GroupPersistence object = (GroupPersistence)getHibernateTemplate().get(GroupPersistence.class, Integer.valueOf(groupId)); object.setExisted(0); object.setGmtModified(new Date()); getHibernateTemplate().update(object); } @Override public void deleteJob(String user, String jobId) throws ZeusException { GroupBeanOld root = getGlobeGroupBean(); JobBeanOld job = root.getAllSubJobBeans().get(jobId); if (!job.getDepender().isEmpty()) { List<String> deps = new ArrayList<String>(); for (JobBeanOld jb : job.getDepender()) { deps.add(jb.getJobDescriptor().getId()); } throw new ZeusException("该Job正在被其他Job" + deps.toString() + "依赖,无法删除"); } getHibernateTemplate().delete( getHibernateTemplate().get(JobPersistenceOld.class, Long.valueOf(jobId))); } @Override public GroupBeanOld getDownstreamGroupBean(String groupId) { GroupDescriptor group = getGroupDescriptor(groupId); GroupBeanOld result = new GroupBeanOld(group); return getDownstreamGroupBean(result); } @Override public GroupBeanOld getDownstreamGroupBean(GroupBeanOld parent) { if (parent.isDirectory()) { List<GroupDescriptor> children = getChildrenGroup(parent .getGroupDescriptor().getId()); for (GroupDescriptor child : children) { GroupBeanOld childBean = new GroupBeanOld(child); getDownstreamGroupBean(childBean); childBean.setParentGroupBean(parent); parent.getChildrenGroupBeans().add(childBean); } } else { List<Tuple<JobDescriptorOld, JobStatus>> jobs = getChildrenJob(parent .getGroupDescriptor().getId()); for (Tuple<JobDescriptorOld, JobStatus> tuple : jobs) { JobBeanOld JobBeanOld = new JobBeanOld(tuple.getX(), tuple.getY()); JobBeanOld.setGroupBean(parent); parent.getJobBeans().put(tuple.getX().getId(), JobBeanOld); } } return parent; } @Override public GroupBeanOld getGlobeGroupBean() { return GroupManagerToolOld.buildGlobeGroupBean(this); } /** * 获取叶子组下所有的Job * * @param groupId * @return */ @Override public List<Tuple<JobDescriptorOld, JobStatus>> getChildrenJob(String groupId) { List<JobPersistenceOld> list = getHibernateTemplate().find( "from com.taobao.zeus.store.mysql.persistence.JobPersistenceOld where groupId=" + groupId); List<Tuple<JobDescriptorOld, JobStatus>> result = new ArrayList<Tuple<JobDescriptorOld, JobStatus>>(); if (list != null) { for (JobPersistenceOld j : list) { result.add(PersistenceAndBeanConvertOld.convert(j)); } } return result; } /** * 获取组的下级组列表 * * @param groupId * @return */ @Override public List<GroupDescriptor> getChildrenGroup(String groupId) { List<GroupPersistence> list = getHibernateTemplate().find( "from com.taobao.zeus.store.mysql.persistence.GroupPersistence where parent=" + groupId); List<GroupDescriptor> result = new ArrayList<GroupDescriptor>(); if (list != null) { for (GroupPersistence p : list) { result.add(PersistenceAndBeanConvertOld.convert(p)); } } return result; } @Override public GroupDescriptor getGroupDescriptor(String groupId) { GroupPersistence persist = (GroupPersistence) getHibernateTemplate() .get(GroupPersistence.class, Integer.valueOf(groupId)); if (persist != null) { return PersistenceAndBeanConvertOld.convert(persist); } return null; } @Override public Tuple<JobDescriptorOld, JobStatus> getJobDescriptor(String jobId) { JobPersistenceOld persist = getJobPersistence(jobId); if (persist == null) { return null; } Tuple<JobDescriptorOld, JobStatus> t = PersistenceAndBeanConvertOld .convert(persist); JobDescriptorOld jd = t.getX(); // 如果是周期任务,并且依赖不为空,则需要封装周期任务的依赖 if (jd.getScheduleType() == JobScheduleTypeOld.CyleJob && jd.getDependencies() != null) { JobPersistenceOld jp = null; for (String jobID : jd.getDependencies()) { if (StringUtils.isNotEmpty(jobID)) { jp = getJobPersistence(jobID); if(jp!=null){ jd.getDepdCycleJob().put(jobID, jp.getCycle()); } } } } return t; } private JobPersistenceOld getJobPersistence(String jobId) { JobPersistenceOld persist = (JobPersistenceOld) getHibernateTemplate().get( JobPersistenceOld.class, Long.valueOf(jobId)); if (persist == null) { return null; } return persist; } @Override public String getRootGroupId() { return (String) getHibernateTemplate().execute(new HibernateCallback() { @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = session .createQuery("from com.taobao.zeus.store.mysql.persistence.GroupPersistence g order by g.id asc"); query.setMaxResults(1); List<GroupPersistence> list = query.list(); if (list == null || list.size() == 0) { GroupPersistence persist = new GroupPersistence(); persist.setName("众神之神"); persist.setOwner(ZeusUser.ADMIN.getUid()); persist.setDirectory(0); session.save(persist); if (persist.getId() == null) { return null; } return String.valueOf(persist.getId()); } return String.valueOf(list.get(0).getId()); } }); } @Override public GroupBeanOld getUpstreamGroupBean(String groupId) { return GroupManagerToolOld.getUpstreamGroupBean(groupId, this); } @Override public JobBeanOld getUpstreamJobBean(String jobId) { return GroupManagerToolOld.getUpstreamJobBean(jobId, this); } @Override public void updateGroup(String user, GroupDescriptor group) throws ZeusException { GroupPersistence old = (GroupPersistence) getHibernateTemplate().get( GroupPersistence.class, Integer.valueOf(group.getId())); updateGroup(user, group, old.getOwner(), old.getParent() == null ? null : old.getParent().toString()); } public void updateGroup(String user, GroupDescriptor group, String owner, String parent) throws ZeusException { GroupPersistence old = (GroupPersistence) getHibernateTemplate().get( GroupPersistence.class, Integer.valueOf(group.getId())); GroupPersistence persist = PersistenceAndBeanConvertOld.convert(group); persist.setOwner(owner); if (parent != null) { persist.setParent(Integer.valueOf(parent)); } // 以下属性不允许修改,强制采用老的数据 persist.setDirectory(old.getDirectory()); persist.setGmtCreate(old.getGmtCreate()); persist.setGmtModified(new Date()); persist.setExisted(old.getExisted()); getHibernateTemplate().update(persist); } @Override public void updateJob(String user, JobDescriptorOld job) throws ZeusException { JobPersistenceOld orgPersist = (JobPersistenceOld) getHibernateTemplate() .get(JobPersistenceOld.class, Long.valueOf(job.getId())); updateJob(user, job, orgPersist.getOwner(), orgPersist.getGroupId() .toString()); } public void updateJob(String user, JobDescriptorOld job, String owner, String groupId) throws ZeusException { JobPersistenceOld orgPersist = (JobPersistenceOld) getHibernateTemplate() .get(JobPersistenceOld.class, Long.valueOf(job.getId())); if (job.getScheduleType() == JobScheduleTypeOld.Independent) { job.setDependencies(new ArrayList<String>()); } else if (job.getScheduleType() == JobScheduleTypeOld.Dependent) { job.setCronExpression(""); } job.setOwner(owner); job.setGroupId(groupId); // 以下属性不允许修改,强制采用老的数据 JobPersistenceOld persist = PersistenceAndBeanConvertOld.convert(job); persist.setGmtCreate(orgPersist.getGmtCreate()); persist.setGmtModified(new Date()); persist.setRunType(orgPersist.getRunType()); persist.setStatus(orgPersist.getStatus()); persist.setReadyDependency(orgPersist.getReadyDependency()); persist.setHost(job.getHost()); persist.setHostGroupId(Integer.valueOf(job.getHostGroupId())); // 如果是用户从界面上更新,开始时间、统计周期等均为空,用原来的值 if (job.getStartTime() == null || "".equals(job.getStartTime())) { persist.setStartTime(orgPersist.getStartTime()); } if (job.getStartTimestamp() == 0) { persist.setStartTimestamp(orgPersist.getStartTimestamp()); } if (job.getStatisStartTime() == null || "".equals(job.getStatisStartTime())) { persist.setStatisStartTime(orgPersist.getStatisStartTime()); } if (job.getStatisEndTime() == null || "".equals(job.getStatisEndTime())) { persist.setStatisEndTime(orgPersist.getStatisEndTime()); } // 如果是周期任务,则许检查依赖周期是否正确 if (JobScheduleTypeOld.CyleJob.equals(job.getScheduleType()) && job.getDependencies() != null && job.getDependencies().size() != 0) { List<JobDescriptorOld> list = this.getJobDescriptors(job .getDependencies()); jobValidateOld.checkCycleJob(job, list); } if (jobValidateOld.valide(job)) { getHibernateTemplate().update(persist); } } @Autowired private JobValidateOld jobValidateOld; @Override public GroupDescriptor createGroup(String user, String groupName, String parentGroup, boolean isDirectory) throws ZeusException { if (parentGroup == null) { throw new ZeusException("parent group may not be null"); } GroupDescriptor group = new GroupDescriptor(); group.setOwner(user); group.setName(groupName); group.setParent(parentGroup); group.setDirectory(isDirectory); GroupValidate.valide(group); GroupPersistence persist = PersistenceAndBeanConvertOld.convert(group); persist.setGmtCreate(new Date()); persist.setGmtModified(new Date()); persist.setExisted(1); getHibernateTemplate().save(persist); return PersistenceAndBeanConvertOld.convert(persist); } @Override public JobDescriptorOld createJob(String user, String jobName, String parentGroup, JobRunTypeOld jobType) throws ZeusException { GroupDescriptor parent = getGroupDescriptor(parentGroup); if (parent.isDirectory()) { throw new ZeusException("目录组下不得创建Job"); } JobDescriptorOld job = new JobDescriptorOld(); job.setOwner(user); job.setName(jobName); job.setGroupId(parentGroup); job.setJobType(jobType); job.setPreProcessers(Arrays.asList((Processer) new DownloadProcesser())); JobPersistenceOld persist = PersistenceAndBeanConvertOld.convert(job); persist.setGmtCreate(new Date()); persist.setGmtModified(new Date()); getHibernateTemplate().save(persist); return PersistenceAndBeanConvertOld.convert(persist).getX(); } @Override public Map<String, Tuple<JobDescriptorOld, JobStatus>> getJobDescriptor( final Collection<String> jobIds) { List<Tuple<JobDescriptorOld, JobStatus>> list = (List<Tuple<JobDescriptorOld, JobStatus>>) getHibernateTemplate() .execute(new HibernateCallback() { @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { if (jobIds.isEmpty()) { return Collections.emptyList(); } List<Long> ids = new ArrayList<Long>(); for (String i : jobIds) { ids.add(Long.valueOf(i)); } Query query = session .createQuery("from com.taobao.zeus.store.mysql.persistence.JobPersistenceOld where id in (:list)"); query.setParameterList("list", ids); List<JobPersistenceOld> list = query.list(); List<Tuple<JobDescriptorOld, JobStatus>> result = new ArrayList<Tuple<JobDescriptorOld, JobStatus>>(); if (list != null && !list.isEmpty()) { for (JobPersistenceOld persist : list) { result.add(PersistenceAndBeanConvertOld .convert(persist)); } } return result; } }); Map<String, Tuple<JobDescriptorOld, JobStatus>> map = new HashMap<String, Tuple<JobDescriptorOld, JobStatus>>(); for (Tuple<JobDescriptorOld, JobStatus> jd : list) { map.put(jd.getX().getId(), jd); } return map; } public List<JobDescriptorOld> getJobDescriptors(final Collection<String> jobIds) { List<JobDescriptorOld> list = (List<JobDescriptorOld>) getHibernateTemplate() .execute(new HibernateCallback() { @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { if (jobIds.isEmpty()) { return Collections.emptyList(); } List<Long> ids = new ArrayList<Long>(); for (String i : jobIds) { if (StringUtils.isNotEmpty(i)) { ids.add(Long.valueOf(i)); } } if (ids.isEmpty()) { return Collections.emptyList(); } Query query = session .createQuery("from com.taobao.zeus.store.mysql.persistence.JobPersistenceOld where id in (:list)"); query.setParameterList("list", ids); List<JobPersistenceOld> list = query.list(); List<JobDescriptorOld> result = new ArrayList<JobDescriptorOld>(); if (list != null && !list.isEmpty()) { for (JobPersistenceOld persist : list) { result.add(PersistenceAndBeanConvertOld.convert( persist).getX()); } } return result; } }); return list; } @Override public void updateJobStatus(JobStatus jobStatus) { JobPersistenceOld persistence = getJobPersistence(jobStatus.getJobId()); persistence.setGmtModified(new Date()); // 只修改状态 和 依赖 2个字段 JobPersistenceOld temp = PersistenceAndBeanConvertOld.convert(jobStatus); persistence.setStatus(temp.getStatus()); persistence.setReadyDependency(temp.getReadyDependency()); persistence.setHistoryId(temp.getHistoryId()); getHibernateTemplate().update(persistence); } @Override public JobStatus getJobStatus(String jobId) { Tuple<JobDescriptorOld, JobStatus> tuple = getJobDescriptor(jobId); if (tuple == null) { return null; } return tuple.getY(); } @Override public void grantGroupOwner(String granter, String uid, String groupId) throws ZeusException { GroupDescriptor gd = getGroupDescriptor(groupId); if (gd != null) { updateGroup(granter, gd, uid, gd.getParent()); } } @Override public void grantJobOwner(String granter, String uid, String jobId) throws ZeusException { Tuple<JobDescriptorOld, JobStatus> job = getJobDescriptor(jobId); if (job != null) { job.getX().setOwner(uid); updateJob(granter, job.getX(), uid, job.getX().getGroupId()); } } @Override public void moveJob(String uid, String jobId, String groupId) throws ZeusException { JobDescriptorOld jd = getJobDescriptor(jobId).getX(); GroupDescriptor gd = getGroupDescriptor(groupId); if (gd.isDirectory()) { throw new ZeusException("非法操作"); } updateJob(uid, jd, jd.getOwner(), groupId); } @Override public void moveGroup(String uid, String groupId, String newParentGroupId) throws ZeusException { GroupDescriptor gd = getGroupDescriptor(groupId); GroupDescriptor parent = getGroupDescriptor(newParentGroupId); if (!parent.isDirectory()) { throw new ZeusException("非法操作"); } updateGroup(uid, gd, gd.getOwner(), newParentGroupId); } @Override public List<String> getHosts() throws ZeusException { return (List<String>) getHibernateTemplate().execute( new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = session .createQuery("select host from com.taobao.zeus.store.mysql.persistence.Worker"); return query.list(); } }); } @Override public void replaceWorker(Worker worker) throws ZeusException { try { getHibernateTemplate().saveOrUpdate(worker); } catch (DataAccessException e) { throw new ZeusException(e); } } @Override public void removeWorker(String host) throws ZeusException { try { getHibernateTemplate().delete( getHibernateTemplate().get(Worker.class, host)); } catch (DataAccessException e) { throw new ZeusException(e); } } /** * 获取All Jobs * * @param groupId * @return */ @Override public List<JobPersistenceOld> getAllJobs() { List<JobPersistenceOld> list = getHibernateTemplate().find( "from com.taobao.zeus.store.mysql.persistence.JobPersistenceOld "); return list; } @Override public List<String> getAllDependencied(String jobID) { List<JobPersistenceOld> jobs = getAllJobs(); if( jobs == null || jobs.size() == 0) return null; Map<String, List<String>> allJobDependencied = new HashMap<String, List<String>>(); for(JobPersistenceOld job : jobs){ JobDescriptorOld jobd = PersistenceAndBeanConvertOld.convert(job).getX(); if( jobd != null && jobd.hasDependencies()){ List<String> deps = jobd.getDependencies(); for(String dep : deps){ List<String> depds = allJobDependencied.get(dep); if(depds == null){ depds = new ArrayList<String>(); } depds.add(job.getId().toString()); allJobDependencied.put(dep, depds); } } } List<String> dependencied = new ArrayList<String>(); Set<String> visited = new HashSet<String>(); Queue<String> idQueue = new LinkedList<String>(); idQueue.offer(jobID); visited.add(jobID); while (!idQueue.isEmpty()) { String id = idQueue.poll(); List<String> depdList = allJobDependencied.get(id); if(depdList !=null && depdList.size() != 0){ for (String depd : depdList) { if (!visited.contains(depd)) { visited.add(depd); idQueue.offer(depd); dependencied.add(depd); } } } } return dependencied; } @Override public List<String> getAllDependencies(String jobID) { JobDescriptorOld job = getJobDescriptor(jobID).getX(); if(job == null || !job.hasDependencies()) return null; List<String> dependencies = new ArrayList<String>(); Set<String> visited = new HashSet<String>(); Queue<String> idQueue = new LinkedList<String>(); idQueue.offer(jobID); visited.add(jobID); while (!idQueue.isEmpty()) { String id = idQueue.poll(); JobDescriptorOld jb = getJobDescriptor(id).getX(); if (jb != null && jb.hasDependencies()) { List<String> deps = jb.getDependencies(); if (deps != null && deps.size() != 0) { for (String dep : deps) { if (!visited.contains(dep)) { visited.add(dep); idQueue.offer(dep); dependencies.add(dep); } } } } } return dependencies; } @Override public void updateActionList(JobDescriptorOld job) { JobPersistenceOld persist = PersistenceAndBeanConvertOld.convert(job); Long jobId = persist.getId(); /* String script = persist.getScript();*/ String resources = persist.getResources(); String configs = persist.getConfigs(); String host = persist.getHost(); Integer workGroupId = persist.getHostGroupId(); Integer auto = persist.getAuto(); logger.info("begin updateActionList."); HibernateTemplate template = getHibernateTemplate(); List<JobPersistence> actionList = template.find("from com.taobao.zeus.store.mysql.persistence.JobPersistence where toJobId='"+ jobId +"' order by id desc"); logger.info("finish query."); if (actionList != null && actionList.size() > 0 ){ for(JobPersistence actionPer : actionList){ // if(!"running".equalsIgnoreCase(actionPer.getStatus())){ /* actionPer.setScript(script);*/ actionPer.setResources(resources); actionPer.setConfigs(configs); actionPer.setHost(host); actionPer.setGmtModified(new Date()); actionPer.setHostGroupId(workGroupId); actionPer.setAuto(auto); template.saveOrUpdate(actionPer); // } } logger.info("finish update " + actionList.size() + "."); } } }