/* * Copyright (C) 2008 Universidade Federal de Campina Grande * * This file is part of OurGrid. * * OurGrid is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * * 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 Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package org.ourgrid.worker.business.controller; import static org.ourgrid.common.CommonConstants.PUT_TRANSFER; import static org.ourgrid.common.CommonConstants.STORE_TRANSFER; import java.io.File; import java.io.IOException; import java.util.LinkedList; import java.util.List; import org.ourgrid.common.FileTransferInfo; import org.ourgrid.common.interfaces.to.GridProcessErrorTypes; import org.ourgrid.common.interfaces.to.IncomingHandle; import org.ourgrid.common.interfaces.to.OutgoingHandle; import org.ourgrid.common.interfaces.to.WorkAccounting; import org.ourgrid.common.internal.IResponseTO; import org.ourgrid.common.internal.response.CancelIncomingTransferResponseTO; import org.ourgrid.common.internal.response.CancelOutgoingTransferResponseTO; import org.ourgrid.common.internal.response.LoggerResponseTO; import org.ourgrid.common.util.FileTransferHandlerUtils; import org.ourgrid.reqtrace.Req; import org.ourgrid.worker.business.dao.FileTransferDAO; import org.ourgrid.worker.business.dao.WorkAccountingDAO; import org.ourgrid.worker.business.dao.WorkerDAOFactory; import org.ourgrid.worker.business.dao.WorkerStatusDAO; import org.ourgrid.worker.business.messages.FileTransferControllerMessages; import org.ourgrid.worker.response.AcceptTransferResponseTO; import org.ourgrid.worker.response.ErrorOcurredMessageHandleResponseTO; import org.ourgrid.worker.response.RejectTransferResponseTO; import org.ourgrid.worker.response.StartTransferResponseTO; public class FileTransferController { private static FileTransferController instance = null; @Req("REQ080") public static synchronized FileTransferController getInstance() { if (instance == null) { instance = new FileTransferController(); } return instance; } @Req("REQ080") public void cancelCurrentTransfers(List<IResponseTO> responses) { FileTransferDAO fileTransferDAO = WorkerDAOFactory.getInstance().getFileTransferDAO(); for (IncomingHandle handle : fileTransferDAO.getIncomingFileHandles()) { CancelIncomingTransferResponseTO to = new CancelIncomingTransferResponseTO(); to.setIncomingHandle(handle); responses.add(to); fileTransferDAO.removeIncomingFile(handle); } for (OutgoingHandle handle : fileTransferDAO.getUploadingFileHandles()) { CancelOutgoingTransferResponseTO to = new CancelOutgoingTransferResponseTO(); to.setOutgoingHandle(handle); responses.add(to); fileTransferDAO.removeUploadingFile(handle); } } @Req("REQ080") public void rejectTransferRequest(IncomingHandle handle, List<IResponseTO> responses) { RejectTransferResponseTO to = new RejectTransferResponseTO(); to.setIncomingHandle(handle); responses.add(to); } @Req("REQ081") private void rejectInvalidRequest(IncomingHandle handle, List<IResponseTO> responses) { RejectTransferResponseTO to = new RejectTransferResponseTO(); to.setIncomingHandle(handle); responses.add(to); cancelCurrentTransfers(responses); WorkerDAOFactory.getInstance().getWorkerStatusDAO().setFileTransferErrorState(true); } @Req("REQ080") public void acceptTransferRequest(IncomingHandle handle, String destinationFile, List<IResponseTO> responses) { String path = destinationFile; String transferDescription = FileTransferHandlerUtils.getOperationType(handle.getDescription()); WorkerStatusDAO workerStatusDAO = WorkerDAOFactory.getInstance().getWorkerStatusDAO(); FileTransferDAO fileTransferDAO = WorkerDAOFactory.getInstance().getFileTransferDAO(); String consumerPublicKey = workerStatusDAO.getConsumerPublicKey(); if (!validateTransferDescription(transferDescription)) { responses.add(new LoggerResponseTO(FileTransferControllerMessages. getClientRequestsToTransferFileWithInvalidTransferDescription(transferDescription, consumerPublicKey), LoggerResponseTO.WARN)); rejectInvalidRequest(handle, responses); return; } if (fileTransferDAO.containsHandle(handle)) { responses.add(new LoggerResponseTO(FileTransferControllerMessages. getClientRequestsToTransferFileWithRepeatedHandleMessage(handle.getId(), consumerPublicKey), LoggerResponseTO.ERROR)); errorOcurred(GridProcessErrorTypes.INVALID_SESSION, responses); cancelCurrentTransfers(responses); return; } String solvedDir; try { if (transferDescription.equals(PUT_TRANSFER)) { solvedDir = EnvironmentController.getInstance().solveDir(path); } else { solvedDir = EnvironmentController.getInstance().solveStorageDir(path); } } catch (IOException e) { responses.add(new LoggerResponseTO(FileTransferControllerMessages. getClientRequestsToTranferFileButErrorOccuredOnSolvingPathMessage(path, handle.getFileSize(), handle.getId(), consumerPublicKey, e.getMessage()), LoggerResponseTO.WARN)); rejectInvalidRequest(handle, responses); return; } if (fileTransferDAO.containsIncomingFile(solvedDir)) { responses.add(new LoggerResponseTO(FileTransferControllerMessages. getClientRequestsToTranferIncomingFileMessage(solvedDir, consumerPublicKey), LoggerResponseTO.WARN)); rejectInvalidRequest(handle, responses); return; } responses.add(new LoggerResponseTO(FileTransferControllerMessages. getTransferRequestAcceptedMessage(solvedDir, handle.getId(), consumerPublicKey), LoggerResponseTO.DEBUG)); File file = new File(solvedDir); fileTransferDAO.addIncomingFile(handle, solvedDir); AcceptTransferResponseTO to = new AcceptTransferResponseTO(); to.setIncomingHandle(handle); to.setFile(file); responses.add(to); } private boolean validateTransferDescription(String transferDescription) { return (PUT_TRANSFER.equals(transferDescription) || STORE_TRANSFER.equals(transferDescription)); } private void increaseWorkDataAccounting(long amount, boolean finishAccount) { WorkAccountingDAO workAccountingDAO = WorkerDAOFactory.getInstance().getWorkAccountingDAO(); WorkAccounting currentWorkAccounting = workAccountingDAO.getCurrentWorkAccounting(); if (currentWorkAccounting != null) { currentWorkAccounting.incDataTransfered(amount); //finish current accounting if (finishAccount) { workAccountingDAO.addWorkAccounting(currentWorkAccounting); workAccountingDAO.setCurrentWorkAccounting(null); } } } @Req("REQ080") public void incomingTransferFailed(IncomingHandle handle, Exception failCause, long amountWritten, List<IResponseTO> responses) { String incomingFileFailedPath = WorkerDAOFactory.getInstance().getFileTransferDAO().removeIncomingFile(handle); String consumerPublicKey = WorkerDAOFactory.getInstance().getWorkerStatusDAO().getConsumerPublicKey(); increaseWorkDataAccounting(amountWritten, false); responses.add(new LoggerResponseTO(FileTransferControllerMessages. getIncomingTransferFailedMessage(incomingFileFailedPath, amountWritten, consumerPublicKey), LoggerResponseTO.ERROR)); errorOcurred(failCause, GridProcessErrorTypes.FILE_TRANSFER_ERROR, responses); } @Req("REQ080") public void incomingTransferCompleted(IncomingHandle handle, long amountWritten, List<IResponseTO> responses) { WorkerDAOFactory.getInstance().getFileTransferDAO().removeIncomingFile(handle); String consumerPublicKey = WorkerDAOFactory.getInstance().getWorkerStatusDAO().getConsumerPublicKey(); increaseWorkDataAccounting(amountWritten, false); responses.add(new LoggerResponseTO(FileTransferControllerMessages. getIncomingTransferCompletedMessage(handle.getId(), amountWritten, consumerPublicKey), LoggerResponseTO.DEBUG)); } @Req("REQ081") private void errorOcurred(Exception exception, GridProcessErrorTypes error, List<IResponseTO> responses) { WorkerStatusDAO workerStatusDAO = WorkerDAOFactory.getInstance().getWorkerStatusDAO(); responses.add(new ErrorOcurredMessageHandleResponseTO(new GridProcessError(exception, error), workerStatusDAO.getConsumerAddress())); cancelCurrentTransfers(responses); workerStatusDAO.setFileTransferErrorState(true); } @Req("REQ081") private void errorOcurred(GridProcessErrorTypes error, List<IResponseTO> responses) { errorOcurred(null, error, responses); } @Req("REQ081") public void fileRejected(OutgoingHandle handle, List<IResponseTO> responses) { String consumerPublicKey = WorkerDAOFactory.getInstance().getWorkerStatusDAO().getConsumerPublicKey(); String rejectedFilePath = WorkerDAOFactory.getInstance().getFileTransferDAO().getUploadingFile(handle).getAbsolutePath(); responses.add(new LoggerResponseTO(FileTransferControllerMessages.getWorkerReceivesAFileTransferRejectedMessage( rejectedFilePath, handle.getId(), consumerPublicKey), LoggerResponseTO.ERROR)); errorOcurred(GridProcessErrorTypes.APPLICATION_ERROR, responses); } @Req("REQ081") public void outgoingTransferFailed(OutgoingHandle handle, Exception exception, long amountUploaded, List<IResponseTO> responses) { String consumerPublicKey = WorkerDAOFactory.getInstance().getWorkerStatusDAO().getConsumerPublicKey(); String failedFilePath = WorkerDAOFactory.getInstance().getFileTransferDAO().getUploadingFile(handle).getAbsolutePath(); increaseWorkDataAccounting(amountUploaded, true); responses.add(new LoggerResponseTO(FileTransferControllerMessages. getWorkerReceivesAnOutgoingFileTransferFailedMessage( failedFilePath, handle.getId(), amountUploaded, consumerPublicKey), LoggerResponseTO.ERROR)); errorOcurred(GridProcessErrorTypes.APPLICATION_ERROR, responses); } @Req("REQ081") public void outgoingTransferCancelled(OutgoingHandle handle, long amountUploaded, List<IResponseTO> responses) { String consumerPublicKey = WorkerDAOFactory.getInstance().getWorkerStatusDAO().getConsumerPublicKey(); String cancelledFilePath = WorkerDAOFactory.getInstance().getFileTransferDAO().getUploadingFile(handle).getAbsolutePath(); increaseWorkDataAccounting(amountUploaded, true); responses.add(new LoggerResponseTO(FileTransferControllerMessages. getWorkerReceivesAnOutgoingFileTransferCancelledMessage( cancelledFilePath, handle.getId(), amountUploaded, consumerPublicKey), LoggerResponseTO.ERROR)); errorOcurred(GridProcessErrorTypes.APPLICATION_ERROR, responses); } @Req("REQ081") public void outgoingTransferCompleted(OutgoingHandle handle, long amountUploaded, List<IResponseTO> responses) { FileTransferDAO fileTransferDAO = WorkerDAOFactory.getInstance().getFileTransferDAO(); String consumerPublicKey = WorkerDAOFactory.getInstance().getWorkerStatusDAO().getConsumerPublicKey(); String filePath = fileTransferDAO.removeUploadingFile(handle); boolean hasUploadingFile = fileTransferDAO.hasUploadingFile(); increaseWorkDataAccounting(amountUploaded, !hasUploadingFile); responses.add(new LoggerResponseTO(FileTransferControllerMessages. getWorkerReceivesAnOutgoingFileTransferCompletedMessage(filePath, handle.getId(), amountUploaded, consumerPublicKey), LoggerResponseTO.DEBUG)); if(!hasUploadingFile) { responses.add(new LoggerResponseTO(FileTransferControllerMessages.getAllUploadsFinishMessage(), LoggerResponseTO.INFO)); } } @Req("REQ081") public void startTransfer(String destinationID, String destPublicKey, List<IResponseTO> responses, FileTransferInfo... files) { List<FileTransferInfo> solvedInfos = solveFilesInfo(responses, files); FileTransferDAO fileTransferDAO = WorkerDAOFactory.getInstance().getFileTransferDAO(); if(solvedInfos != null) { for (FileTransferInfo info : solvedInfos) { File file = new File(info.getFilePath()); String filePath = file.getAbsolutePath(); if (fileTransferDAO.containsUploadingFile(filePath)) { responses.add(new LoggerResponseTO(FileTransferControllerMessages. getClientRequestsToRecoverAnUploadingFileMessage(filePath, destPublicKey), LoggerResponseTO.WARN)); return; } responses.add(new LoggerResponseTO(FileTransferControllerMessages.getWorkerStartsFileTransferWithSuccess(filePath, info.getTransferHandleID(), destPublicKey), LoggerResponseTO.DEBUG)); OutgoingHandle outgoingHandle = new OutgoingHandle(info.getTransferHandleID(), file.getName(), file, null, destinationID); StartTransferResponseTO to = new StartTransferResponseTO(); to.setOutgoingHandle(outgoingHandle); responses.add(to); fileTransferDAO.addUploadingFile(outgoingHandle, filePath); } } } @Req("REQ081") private List<FileTransferInfo> solveFilesInfo(List<IResponseTO> responses, FileTransferInfo... files) { String consumerPublicKey = WorkerDAOFactory.getInstance().getWorkerStatusDAO().getConsumerPublicKey(); if(files == null) { responses.add(new LoggerResponseTO(FileTransferControllerMessages. getClientRequestsToRecoverFilesWithNullFilesMessage(consumerPublicKey), LoggerResponseTO.WARN)); errorOcurred(GridProcessErrorTypes.APPLICATION_ERROR, responses); return null; } List<FileTransferInfo> solvedInfoList = new LinkedList<FileTransferInfo>(); for (FileTransferInfo info : files) { String filePath = info.getFilePath(); try { String solvedDir = EnvironmentController.getInstance().solveDir(filePath); if (hasInfoWithSamePath(solvedInfoList, solvedDir)) { responses.add(new LoggerResponseTO(FileTransferControllerMessages. getClientRequestsToRecoverFilesButThereAreFilesWithSamePathMessage(filePath, consumerPublicKey), LoggerResponseTO.WARN)); errorOcurred(GridProcessErrorTypes.APPLICATION_ERROR, responses); return null; } File file = new File(solvedDir); if (!file.exists()) { responses.add(new LoggerResponseTO(FileTransferControllerMessages. getClientRequestsToRecoverAnInexistentFileMessage(solvedDir, consumerPublicKey), LoggerResponseTO.WARN)); errorOcurred(GridProcessErrorTypes.APPLICATION_ERROR, responses); return null; } solvedInfoList.add(new FileTransferInfo(info.getTransferHandleID(), solvedDir)); } catch (IOException e) { responses.add(new LoggerResponseTO(FileTransferControllerMessages. getClientRequestsToRecoverFilesButErrorOccuredOnSolvingPathMessage(filePath, consumerPublicKey, e.getMessage()), LoggerResponseTO.WARN)); errorOcurred(e, GridProcessErrorTypes.IO_ERROR, responses); return null; } } return solvedInfoList; } @Req("REQ081") private boolean hasInfoWithSamePath(List<FileTransferInfo> solvedInfoList, String filePath) { for (FileTransferInfo info : solvedInfoList) { if (info.getFilePath().equals(filePath)) { return true; } } return false; } }