Package com.cloud.storage.download

Source Code of com.cloud.storage.download.DownloadListener$TimeoutTask

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 com.cloud.storage.download;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.AgentControlCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.agent.api.storage.DownloadCommand;
import com.cloud.agent.api.storage.DownloadProgressCommand;
import com.cloud.agent.api.storage.DownloadCommand.ResourceType;
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConnectionException;
import com.cloud.host.HostVO;

import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VolumeHostVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.Volume.Event;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeHostDao;
import com.cloud.storage.download.DownloadState.DownloadEvent;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;

/**
* Monitor progress of template download to a single storage server
*
*/
public class DownloadListener implements Listener {


  private static final class StatusTask extends TimerTask {
    private final DownloadListener dl;
    private final RequestType reqType;
   
    public StatusTask( DownloadListener dl,  RequestType req) {
      this.reqType = req;
      this.dl = dl;
    }

    @Override
    public void run() {
      dl.sendCommand(reqType);

    }
  }
 
  private static final class TimeoutTask extends TimerTask {
    private final DownloadListener dl;
   
    public TimeoutTask( DownloadListener dl) {
      this.dl = dl;
    }

    @Override
    public void run() {
      dl.checkProgress();
    }
  }


  public static final Logger s_logger = Logger.getLogger(DownloadListener.class.getName());
  public static final int SMALL_DELAY = 100;
    public static final long STATUS_POLL_INTERVAL = 10000L;
 
  public static final String DOWNLOADED=Status.DOWNLOADED.toString();
  public static final String NOT_DOWNLOADED=Status.NOT_DOWNLOADED.toString();
  public static final String DOWNLOAD_ERROR=Status.DOWNLOAD_ERROR.toString();
  public static final String DOWNLOAD_IN_PROGRESS=Status.DOWNLOAD_IN_PROGRESS.toString();
  public static final String DOWNLOAD_ABANDONED=Status.ABANDONED.toString();


  private HostVO sserver;
  private HostVO ssAgent;
  private VMTemplateVO template;
  private VolumeVO volume;
 
  private boolean downloadActive = true;

  private VolumeHostDao volumeHostDao;
  private VolumeDao _volumeDao;
  private StorageManager _storageMgr;
  private VMTemplateHostDao vmTemplateHostDao;
  private VMTemplateDao _vmTemplateDao;

  private final DownloadMonitorImpl downloadMonitor;
 
  private DownloadState currState;
 
  private DownloadCommand cmd;

  private Timer timer;

  private StatusTask statusTask;
  private TimeoutTask timeoutTask;
  private Date lastUpdated = new Date();
  private String jobId;
 
  private final Map<String,  DownloadState> stateMap = new HashMap<String, DownloadState>();
  private Long templateHostId;
  private Long volumeHostId;
 
  public DownloadListener(HostVO ssAgent, HostVO host, VMTemplateVO template, Timer _timer, VMTemplateHostDao dao, Long templHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao) {
      this.ssAgent = ssAgent;
        this.sserver = host;
    this.template = template;
    this.vmTemplateHostDao = dao;
    this.downloadMonitor = downloadMonitor;
    this.cmd = cmd;
    this.templateHostId = templHostId;
    initStateMachine();
    this.currState=getState(Status.NOT_DOWNLOADED.toString());
    this.timer = _timer;
    this.timeoutTask = new TimeoutTask(this);
    this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL);
    this._vmTemplateDao = templateDao;
    updateDatabase(Status.NOT_DOWNLOADED, "");
  }
 
  public DownloadListener(HostVO ssAgent, HostVO host, VolumeVO volume, Timer _timer, VolumeHostDao dao, Long volHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao, StorageManager storageMgr) {
      this.ssAgent = ssAgent;
        this.sserver = host;
    this.volume = volume;
    this.volumeHostDao = dao;
    this.downloadMonitor = downloadMonitor;
    this.cmd = cmd;
    this.volumeHostId = volHostId;
    initStateMachine();
    this.currState=getState(Status.NOT_DOWNLOADED.toString());
    this.timer = _timer;
    this.timeoutTask = new TimeoutTask(this);
    this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL);
    this._volumeDao = volumeDao;
    this._storageMgr = storageMgr;
    updateDatabase(Status.NOT_DOWNLOADED, "");
  }
 
 
  public void setCurrState(VMTemplateHostVO.Status currState) {
    this.currState = getState(currState.toString());
  }

  private void initStateMachine() {
    stateMap.put(Status.NOT_DOWNLOADED.toString(), new NotDownloadedState(this));
    stateMap.put(Status.DOWNLOADED.toString(), new DownloadCompleteState(this));
    stateMap.put(Status.DOWNLOAD_ERROR.toString(), new DownloadErrorState(this));
    stateMap.put(Status.DOWNLOAD_IN_PROGRESS.toString(), new DownloadInProgressState(this));
    stateMap.put(Status.ABANDONED.toString(), new DownloadAbandonedState(this));
  }
 
  private DownloadState getState(String stateName) {
    return stateMap.get(stateName);
  }

  public void sendCommand(RequestType reqType) {
    if (getJobId() != null) {
      if (s_logger.isTraceEnabled()) {
        log("Sending progress command ", Level.TRACE);
      }
      try {
        DownloadProgressCommand dcmd = new DownloadProgressCommand(getCommand(), getJobId(), reqType);
        if (template == null){
          dcmd.setResourceType(ResourceType.VOLUME);
        }
              downloadMonitor.send(ssAgent.getId(), dcmd, this);
            } catch (AgentUnavailableException e) {
              s_logger.debug("Send command failed", e);
        setDisconnected();
            }     
    }

  }

  public void checkProgress() {
    transition(DownloadEvent.TIMEOUT_CHECK, null);
  }

  public void setDisconnected() {
    transition(DownloadEvent.DISCONNECT, null);
  }

  public void logDisconnect() {
    if (template != null){
      s_logger.warn("Unable to monitor download progress of " + template.getName() + " at host " + sserver.getName());
    }else {
      s_logger.warn("Unable to monitor download progress of " + volume.getName() + " at host " + sserver.getName());
    }
  }

  public synchronized void updateDatabase(Status state, String errorString) {
    if (template != null){
        VMTemplateHostVO vo = vmTemplateHostDao.createForUpdate();
      vo.setDownloadState(state);
      vo.setLastUpdated(new Date());
      vo.setErrorString(errorString);
      vmTemplateHostDao.update(getTemplateHostId(), vo);
    }else {
        VolumeHostVO vo = volumeHostDao.createForUpdate();
      vo.setDownloadState(state);
      vo.setLastUpdated(new Date());
      vo.setErrorString(errorString);
      volumeHostDao.update(getVolumeHostId(), vo);
    }
  }
 
  public void log(String message, Level level) {
    if (template != null){
      s_logger.log(level, message + ", template=" + template.getName() + " at host " + sserver.getName());
    }else {
      s_logger.log(level, message + ", volume=" + volume.getName() + " at host " + sserver.getName());
    }
  }

  private Long getTemplateHostId() {
    if (templateHostId == null){
      VMTemplateHostVO templHost = vmTemplateHostDao.findByHostTemplate(sserver.getId(), template.getId());
      templateHostId = templHost.getId();
    }
    return templateHostId;
  }
 
  private Long getVolumeHostId() {
    if (volumeHostId == null){
      VolumeHostVO volHost = volumeHostDao.findByHostVolume(sserver.getId(), volume.getId());
      volumeHostId = volHost.getId();
    }
    return volumeHostId;
  }

  public DownloadListener(DownloadMonitorImpl monitor) {
      downloadMonitor = monitor;
  }

 

  @Override
  public boolean isRecurring() {
    return false;
  }

 
  @Override
  public boolean processAnswers(long agentId, long seq, Answer[] answers) {
    boolean processed = false;
      if(answers != null & answers.length > 0) {
        if(answers[0] instanceof DownloadAnswer) {
          final DownloadAnswer answer = (DownloadAnswer)answers[0];
          if (getJobId() == null) {
            setJobId(answer.getJobId());
          } else if (!getJobId().equalsIgnoreCase(answer.getJobId())){
            return false;//TODO
          }
          transition(DownloadEvent.DOWNLOAD_ANSWER, answer);
          processed = true;
        }
      }
        return processed;
  }
 
  private synchronized void transition(DownloadEvent event, Object evtObj) {
      if (currState == null) {
          return;
      }
    String prevName = currState.getName();
    String nextState = currState.handleEvent(event, evtObj);
    if (nextState != null) {
      currState = getState(nextState);
      if (currState != null) {
        currState.onEntry(prevName, event, evtObj);
      } else {
        throw new CloudRuntimeException("Invalid next state: currState="+prevName+", evt="+event + ", next=" + nextState);
      }
    } else {
      throw new CloudRuntimeException("Unhandled event transition: currState="+prevName+", evt="+event);
    }
  }

  public synchronized void updateDatabase(DownloadAnswer answer) {
    if (template != null){
          VMTemplateHostVO updateBuilder = vmTemplateHostDao.createForUpdate();
      updateBuilder.setDownloadPercent(answer.getDownloadPct());
      updateBuilder.setDownloadState(answer.getDownloadStatus());
      updateBuilder.setLastUpdated(new Date());
      updateBuilder.setErrorString(answer.getErrorString());
      updateBuilder.setJobId(answer.getJobId());
      updateBuilder.setLocalDownloadPath(answer.getDownloadPath());
      updateBuilder.setInstallPath(answer.getInstallPath());
      updateBuilder.setSize(answer.getTemplateSize());
      updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
     
      vmTemplateHostDao.update(getTemplateHostId(), updateBuilder);
     
      if (answer.getCheckSum() != null) {
        VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate();
        templateDaoBuilder.setChecksum(answer.getCheckSum());
        _vmTemplateDao.update(template.getId(), templateDaoBuilder);
      }
    } else {
          VolumeHostVO updateBuilder = volumeHostDao.createForUpdate();
      updateBuilder.setDownloadPercent(answer.getDownloadPct());
      updateBuilder.setDownloadState(answer.getDownloadStatus());
      updateBuilder.setLastUpdated(new Date());
      updateBuilder.setErrorString(answer.getErrorString());
      updateBuilder.setJobId(answer.getJobId());
      updateBuilder.setLocalDownloadPath(answer.getDownloadPath());
      updateBuilder.setInstallPath(answer.getInstallPath());
      updateBuilder.setSize(answer.getTemplateSize());
      updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
     
      volumeHostDao.update(getVolumeHostId(), updateBuilder);
      /*if (answer.getCheckSum() != null) {
        VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate();
        templateDaoBuilder.setChecksum(answer.getCheckSum());
        _vmTemplateDao.update(template.getId(), templateDaoBuilder);
      }*/
    }
   }

  @Override
  public boolean processCommands(long agentId, long seq, Command[] req) {
    return false;
  }

    @Override
    public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
      return null;
    }

  @Override
  public boolean processDisconnect(long agentId, com.cloud.host.Status state) {
    setDisconnected();
    return true;
  }
 
  @Override
  public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
      if (cmd instanceof StartupRoutingCommand) {
          downloadMonitor.handleSysTemplateDownload(agent);
      } else if ( cmd instanceof StartupStorageCommand) {
          StartupStorageCommand storage = (StartupStorageCommand)cmd;
            if( storage.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE || 
                    storage.getResourceType() == Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE  ) {
                downloadMonitor.addSystemVMTemplatesToHost(agent, storage.getTemplateInfo());
                downloadMonitor.handleTemplateSync(agent);
                downloadMonitor.handleVolumeSync(agent);
            }
      } else if ( cmd instanceof StartupSecondaryStorageCommand ) {       
          downloadMonitor.handleSync(agent.getDataCenterId());
      }
  }

  public void setCommand(DownloadCommand _cmd) {
    this.cmd = _cmd;
  }

  public DownloadCommand getCommand() {
    return cmd;
  }

 
  public void abandon() {
    transition(DownloadEvent.ABANDON_DOWNLOAD, null);
  }

  public void setJobId(String _jobId) {
    this.jobId = _jobId;
  }

  public String getJobId() {
    return jobId;
  }

  public void scheduleStatusCheck(RequestType request) {
    if (statusTask != null) statusTask.cancel();

    statusTask = new StatusTask(this, request);
    timer.schedule(statusTask, STATUS_POLL_INTERVAL);
  }
 
  public void scheduleTimeoutTask(long delay) {
    if (timeoutTask != null) timeoutTask.cancel();

    timeoutTask = new TimeoutTask(this);
    timer.schedule(timeoutTask, delay);
    if (s_logger.isDebugEnabled()) {
      log("Scheduling timeout at " + delay + " ms", Level.DEBUG);
    }
  }
 
  public void scheduleImmediateStatusCheck(RequestType request) {
    if (statusTask != null) statusTask.cancel();
    statusTask = new StatusTask(this, request);
    timer.schedule(statusTask, SMALL_DELAY);
  }

  public boolean isDownloadActive() {
    return downloadActive;
  }

  public void cancelStatusTask() {
    if (statusTask != null) statusTask.cancel();
  }

  public Date getLastUpdated() {
    return lastUpdated;
  }
 
  public void setLastUpdated() {
    lastUpdated  = new Date();
  }

  public void setDownloadInactive(Status reason) {
    downloadActive=false;
    if (template != null){
      downloadMonitor.handleDownloadEvent(sserver, template, reason);
    }else {
      downloadMonitor.handleDownloadEvent(sserver, volume, reason);
    }
  }

  public void cancelTimeoutTask() {
    if (timeoutTask != null) timeoutTask.cancel();
  }

  public void logDownloadStart() {
  }
 
    @Override
    public boolean processTimeout(long agentId, long seq) {
      return true;
    }
   
    @Override
    public int getTimeout() {
      return -1;
    }
}
TOP

Related Classes of com.cloud.storage.download.DownloadListener$TimeoutTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
send', 'pageview');