Java tutorial
/* * Copyright 2017 Huawei Technologies Co., Ltd. * * Licensed 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.openo.gso.job; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TimerTask; import org.apache.commons.collections.map.HashedMap; import org.openo.gso.commsvc.common.util.ValidateUtil; import org.openo.gso.constant.CommonConstant; import org.openo.gso.constant.Constant; import org.openo.gso.dao.inf.IInventoryDao; import org.openo.gso.dao.inf.IServiceModelDao; import org.openo.gso.dao.inf.IServiceOperDao; import org.openo.gso.dao.inf.IServiceSegmentDao; import org.openo.gso.model.servicemo.InvServiceModel; import org.openo.gso.model.servicemo.ServiceModel; import org.openo.gso.model.servicemo.ServiceOperation; import org.openo.gso.model.servicemo.ServiceSegmentOperation; import org.openo.gso.util.convertor.DataConverter; import org.openo.gso.util.service.SpringContextUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.CollectionUtils; /** * Update status task.<br/> * <p> * </p> * * @author * @version GSO 0.5 2017/1/15 */ public class UpdateStatusJob extends TimerTask { /** * Log */ private static final Logger LOGGER = LoggerFactory.getLogger(UpdateStatusJob.class); /** * Service model dao. */ private IServiceModelDao svcModelDao = (IServiceModelDao) SpringContextUtil .getBeanById(Constant.BEAID_SERVICE_MODEL_DAO); /** * Service segment dao. */ private IServiceSegmentDao segmentsDao = (IServiceSegmentDao) SpringContextUtil .getBeanById(Constant.BEAID_SERVICE_SEG_DAO); /** * Service operation dao. */ private IServiceOperDao serviceOperDao = (IServiceOperDao) SpringContextUtil .getBeanById(Constant.BEAID_SERVICE_OPER_DAO); /** * Inventory Service dao. */ private IInventoryDao invDao = (IInventoryDao) SpringContextUtil.getBeanById(Constant.BEAID_INV_DAO); /** * Operation of service without segment not update for 5m */ private static final long SERVICE_WITHOUT_SEG_NOT_UPDATE = 5 * 60 * 1000L; /** * Operation of service with segment not update for 2h. */ private static final long SERVICE_WITH_SEG_NOT_UPDATE = 2 * 60 * 60 * 1000L; /** * The action to be performed by this timer task.<br/> * * @since GSO 0.5 */ @Override public void run() { try { ValidateUtil.assertObjectNotNull(svcModelDao); ValidateUtil.assertObjectNotNull(segmentsDao); ValidateUtil.assertObjectNotNull(serviceOperDao); ValidateUtil.assertObjectNotNull(invDao); // Query service instances by service instance ID, which need to be updated status. List<ServiceModel> svcModels = svcModelDao.queryServiceByStatus(CommonConstant.Status.PROCESSING); if (CollectionUtils.isEmpty(svcModels)) { LOGGER.info("There is no service instance which need to update status."); return; } List<String> svcIds = getSvcIds(svcModels); // Query operation details of service segments by service instance ID. List<ServiceSegmentOperation> segmentOpers = segmentsDao.querySegmentOperByIds(svcIds); if (CollectionUtils.isEmpty(segmentOpers)) { // Update service status when there is no segments operations // At the same time service operation not update for 300s. dealSvcWithoutSegOpers(svcIds, svcModels); return; } // Update service instances status and processing by service segments // size(svcModels) >= size(segmentOpers) updateData(svcModels, segmentOpers); } catch (Exception exception) { LOGGER.error("Fail to update status. {}", exception); } } /** * Get service instances id.<br/> * * @param svcModels service instances * @return service instances id * @since GSO 0.5 */ private List<String> getSvcIds(List<ServiceModel> svcModels) { List<String> svcIds = new LinkedList<>(); for (ServiceModel model : svcModels) { svcIds.add(model.getServiceId()); } LOGGER.info("svcIds is {}", svcIds); return svcIds; } /** * Get unnormal service instance which status is not updated for 5m.<br/> * <p> * Here it is a special service instance which has no segments operation in DB. * </p> * * @param svcOpers service operation * @param time that service operations not update * @return unnormal service instance operation * @since GSO 0.5 */ private List<ServiceOperation> getUnNormalSvcWitoutSegs(List<ServiceOperation> svcOpers, long time) { List<ServiceOperation> unnormal = new LinkedList<>(); for (ServiceOperation oper : svcOpers) { if (((oper.getFinishedAt() - oper.getOperateAt()) > time) || ((System.currentTimeMillis() - oper.getFinishedAt()) > time)) { unnormal.add(oper); } } return unnormal; } /** * Deal service instances which have no segment operations.<br/> * * @param svcIds service instance ID. * @param svcModels service instances. * @since GSO 0.5 */ private void dealSvcWithoutSegOpers(List<String> svcIds, List<ServiceModel> svcModels) { if (CollectionUtils.isEmpty(svcIds)) { LOGGER.info("There is no svcIds which need to be deal with."); return; } // Query unnormal service operation List<ServiceOperation> unnormalOper = getUnNormalSvcWitoutSegs(serviceOperDao.queryOperByIds(svcIds), SERVICE_WITHOUT_SEG_NOT_UPDATE); if (CollectionUtils.isEmpty(unnormalOper)) { return; } // Set service operation status List<String> unnormalSvcIdsAdd = new LinkedList<>(); List<String> unnormalSvcIdsDel = new LinkedList<>(); for (ServiceOperation operation : unnormalOper) { operation.setFinishedAt(System.currentTimeMillis()); operation.setResult(CommonConstant.Status.ERROR); operation.setReason( "The progress of operation is still " + operation.getProgress() + "%, so end operation."); operation.setProgress(Integer.valueOf(CommonConstant.Progress.ONE_HUNDRED).intValue()); if (CommonConstant.OperationType.DELETE.equals(operation.getOperation())) { unnormalSvcIdsDel.add(operation.getServiceId()); } else { unnormalSvcIdsAdd.add(operation.getServiceId()); } } // Update service instance operation serviceOperDao.batchUpdate(unnormalOper); // Assemble service instances which need to update List<InvServiceModel> invServices = new LinkedList<>(); List<ServiceModel> unnormalServices = new LinkedList<>(); for (ServiceModel service : svcModels) { if (unnormalSvcIdsAdd.contains(service.getServiceId())) { service.setStatus(CommonConstant.Status.ERROR); unnormalServices.add(service); invServices.add(DataConverter.convertToInvData(service)); } } if (!CollectionUtils.isEmpty(invServices)) { // Update inventory service status invDao.batchUpdate(invServices); // Update service instance status svcModelDao.batchUpdate(unnormalServices); } if (!CollectionUtils.isEmpty(unnormalSvcIdsDel)) { invDao.batchDelete(unnormalSvcIdsDel); svcModelDao.batchDelete(unnormalSvcIdsDel); } } /** * Update service and operation data.<br/> * * @param services service instances * @param segmentOpers service operations * @since GSO 0.5 */ private void updateData(List<ServiceModel> services, List<ServiceSegmentOperation> segmentOpers) { String serviceId; Map<String, List<ServiceSegmentOperation>> svcSegMaybeNormal = new HashedMap(); Map<String, ServiceSegmentOperation> svcSegError = new HashedMap(); // 1. Sort segments by status for (ServiceSegmentOperation segOper : segmentOpers) { serviceId = segOper.getServiceId(); // Look for error segments. if (CommonConstant.Status.ERROR.equals(segOper.getStatus())) { svcSegError.put(serviceId, segOper); continue; } // Storage maybe normal service segments // Maybe there are segments which progress not update for a long time if (svcSegMaybeNormal.containsKey(serviceId)) { svcSegMaybeNormal.get(serviceId).add(segOper); } else { List<ServiceSegmentOperation> segOpersLst = new LinkedList<>(); segOpersLst.add(segOper); svcSegMaybeNormal.put(serviceId, segOpersLst); } } // 2. Sort service instance. // Service instance without service segments List<ServiceModel> svcWithoutSegs = new LinkedList<>(); // Service instance with error service segment List<ServiceModel> svcWithErrorSegs = new LinkedList<>(); // service instance which status maybe is normal List<ServiceModel> svcMaybeNormal = new LinkedList<>(); for (ServiceModel model : services) { serviceId = model.getServiceId(); if (svcSegError.containsKey(serviceId)) { model.setStatus(CommonConstant.Status.ERROR); svcWithErrorSegs.add(model); } else if (svcSegMaybeNormal.containsKey(serviceId)) { svcMaybeNormal.add(model); } else { svcWithoutSegs.add(model); } } // 3. Update service without segment operations dealSvcWithoutSegOpers(getSvcIds(svcWithoutSegs), svcWithErrorSegs); // 4. Update service status because there is a segment which status is error dealSvcWithErrorSeg(svcWithErrorSegs, svcSegError); // 5. Calculate service progress by the progress of service segments. calcServiceProgess(svcMaybeNormal, svcSegMaybeNormal); } /** * Update service status, which segment status is error.<br/> * * @param svcWithErrorSegs service instances * @param svcSegError service segments * @since GSO 0.5 */ private void dealSvcWithErrorSeg(List<ServiceModel> svcWithErrorSegs, Map<String, ServiceSegmentOperation> svcSegError) { if (CollectionUtils.isEmpty(svcWithErrorSegs)) { LOGGER.info("There is no service instance to update."); return; } // 1. Update service operations List<ServiceOperation> svcOpers = serviceOperDao.queryOperByIds(getSvcIds(svcWithErrorSegs)); for (ServiceOperation operation : svcOpers) { ServiceSegmentOperation segOper = svcSegError.get(operation.getServiceId()); if (null == segOper) { continue; } operation.setResult(CommonConstant.Status.ERROR); operation.setFinishedAt(System.currentTimeMillis()); operation.setProgress(Integer.valueOf(CommonConstant.Progress.ONE_HUNDRED).intValue()); // need to confirm if it is reason item. operation.setReason(segOper.getStatusDescription()); } serviceOperDao.batchUpdate(svcOpers); // 2. Update inventory service instances List<InvServiceModel> invServices = new LinkedList<>(); for (ServiceModel model : svcWithErrorSegs) { invServices.add(DataConverter.convertToInvData(model)); } invDao.batchUpdate(invServices); // 3. Update service instances svcModelDao.batchUpdate(svcWithErrorSegs); } /** * Calculate service operation progress and status.<br/> * * @param services service instances * @param svcSegmentOpers service segment operations * @since GSO 0.5 */ private void calcServiceProgess(List<ServiceModel> services, Map<String, List<ServiceSegmentOperation>> svcSegmentOpers) { if (CollectionUtils.isEmpty(services)) { LOGGER.info("There is no service instance which need to calculate progress."); return; } // 1. Get service operations List<ServiceOperation> svcOperations = serviceOperDao.queryOperByIds(getSvcIds(services)); Map<String, ServiceOperation> svcOperMap = new HashedMap(); for (ServiceOperation oper : svcOperations) { svcOperMap.put(oper.getServiceId(), oper); } List<String> delServiceIds = new LinkedList<>(); // 2. Calculate progress and status int progress; ServiceOperation serviceOper; List<ServiceSegmentOperation> segOperLst; List<InvServiceModel> invServices = new LinkedList<>(); List<ServiceModel> updateSvc = new LinkedList<>(); List<ServiceOperation> updateSvcOper = new LinkedList<>(); for (ServiceModel service : services) { segOperLst = svcSegmentOpers.get(service.getServiceId()); serviceOper = svcOperMap.get(service.getServiceId()); serviceOper.setOperationContent(getOperContent(segOperLst)); // all service segments finish operation. if (isSvcFinished(segOperLst, service.getSegmentNumber())) { if (Constant.OPERATION_DELETE.equals(serviceOper.getOperation())) { delServiceIds.add(service.getServiceId()); } else { service.setStatus(CommonConstant.Status.FINISHED); updateSvc.add(service); invServices.add(DataConverter.convertToInvData(service)); } serviceOper.setProgress(Integer.valueOf(CommonConstant.Progress.ONE_HUNDRED).intValue()); serviceOper.setFinishedAt(System.currentTimeMillis()); serviceOper.setResult(CommonConstant.Status.FINISHED); updateSvcOper.add(serviceOper); continue; } // calculate progress progress = calculateProgerss(segOperLst, service.getSegmentNumber()); if (serviceOper.getProgress() == progress) { // Not update for a long time, think as operation fail. if ((serviceOper.getFinishedAt() - serviceOper.getOperateAt()) > SERVICE_WITH_SEG_NOT_UPDATE) { service.setStatus(CommonConstant.Status.ERROR); updateSvc.add(service); invServices.add(DataConverter.convertToInvData(service)); serviceOper.setProgress(Integer.valueOf(CommonConstant.Progress.ONE_HUNDRED)); serviceOper.setReason("Not update status for 2 hours."); serviceOper.setFinishedAt(System.currentTimeMillis()); updateSvcOper.add(serviceOper); } } else { // Update progress according to real progress serviceOper.setProgress(progress); serviceOper.setFinishedAt(System.currentTimeMillis()); updateSvcOper.add(serviceOper); } } // 3. update table data updateTable(updateSvcOper, updateSvc, invServices, delServiceIds); } /** * Update table data.<br/> * * @param updateSvcOper service operation data * @param updateSvc gso service instance data * @param invServices inventory service instance data * @param delServiceIds service instance IDs which will be deleted * @since GSO 0.5 */ private void updateTable(List<ServiceOperation> updateSvcOper, List<ServiceModel> updateSvc, List<InvServiceModel> invServices, List<String> delServiceIds) { // 1. Update service operations if (!CollectionUtils.isEmpty(updateSvcOper)) { serviceOperDao.batchUpdate(updateSvcOper); } // 2.1 Update gso service status if (!CollectionUtils.isEmpty(updateSvc)) { svcModelDao.batchUpdate(updateSvc); } // 2.2 Update inventory service status if (!CollectionUtils.isEmpty(invServices)) { invDao.batchUpdate(invServices); } // 3. Delete service instances which are being deleted if (!CollectionUtils.isEmpty(delServiceIds)) { svcModelDao.batchDelete(delServiceIds); invDao.batchDelete(delServiceIds); } } /** * Judge if service operation is finished.<br/> * * @param segOperLst service segment operations * @param allSegNum the number of all service segments * @return boolean if the status of all service segments are finished, return true * @since GSO 0.5 */ private boolean isSvcFinished(List<ServiceSegmentOperation> segOperLst, int allSegNum) { if (segOperLst.size() < allSegNum) { return false; } for (ServiceSegmentOperation oper : segOperLst) { if (!CommonConstant.Status.FINISHED.equals(oper.getStatus())) { return false; } } return true; } /** * Calculate progress.<br/> * * @param segOperLst service segment operations * @param allSegNum the number of all service segments * @return progress * @since GSO 0.5 */ private int calculateProgerss(List<ServiceSegmentOperation> segOperLst, int allSegNum) { int progress = 0; for (ServiceSegmentOperation oper : segOperLst) { progress += oper.getProgress(); } return progress / allSegNum; } /** * Get current operation content.<br/> * * @param segOperations operations of segments * @return current operation content * @since GSO 0.5 */ private String getOperContent(List<ServiceSegmentOperation> segOperations) { if (CollectionUtils.isEmpty(segOperations)) { return ""; } for (ServiceSegmentOperation segOper : segOperations) { if (CommonConstant.Status.PROCESSING.equals(segOper.getStatus())) { return segOper.getStatusDescription(); } } return ""; } }