/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.management.backup; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BackupProcessor { private static final Logger log = LoggerFactory.getLogger(BackupProcessor.class); private ExecutorService executor; private CountDownLatch latch; private Map<String, String> hosts; private List<Integer> ports; private String backupTag; private int taskCnt = 0; public BackupProcessor(Map<String, String> hosts, List<Integer> ports, String backupTag) { this.hosts = hosts; this.ports = ports; if (hosts != null && ports != null) { taskCnt = hosts.size() * ports.size(); } if (taskCnt == 0) { throw new IllegalArgumentException( String.format("Invalid argument, hosts:%s ports:%s", hosts, ports)); } this.backupTag = backupTag; this.executor = Executors.newFixedThreadPool(taskCnt); this.latch = new CountDownLatch(taskCnt); } public <T> List<BackupTask<T>> process(BackupCallable<T> callable, final boolean needCancel) throws Exception { List<BackupTask<T>> tasks = new ArrayList<BackupTask<T>>(taskCnt); try { List<BackupRequest> backupRequests = initBackupRequest(); for (BackupRequest request : backupRequests) { BackupCallable<T> task = (BackupCallable<T>) callable.clone(); task.setBackupTag(backupTag); task.setHost(request.host); task.setPort(request.port); task.setLatch(latch); Future<T> future = executor.submit(task); BackupResponse<T> response = new BackupResponse<T>(future); tasks.add(new BackupTask<T>(request, response)); } latch.await(); log.info("all tasks are finished"); } catch (Exception e) { if (needCancel) { log.error("Try to cancel all the tasks for error, e= ", e); for (BackupTask<T> task : tasks) { task.getResponse().getFuture().cancel(true); } } throw e; } finally { executor.shutdown(); } return tasks; } private List<BackupRequest> initBackupRequest() { List<BackupRequest> backupRequests = new ArrayList<BackupRequest>(); for (Map.Entry<String, String> entry : hosts.entrySet()) { for (Integer port : ports) { backupRequests.add(new BackupRequest(entry.getKey(), entry.getValue(), port)); } } return backupRequests; } public class BackupRequest { private final String node; private final String host; private final int port; BackupRequest(String node, String host, int port) { this.node = node; this.host = host; this.port = port; } public String getNode() { return node; } public String getHost() { return host; } public int getPort() { return port; } } public class BackupResponse<T> { private Future<T> future; BackupResponse(Future<T> future) { this.future = future; } public Future<T> getFuture() { return future; } } public class BackupTask<T> { final BackupRequest request; final BackupResponse<T> response; BackupTask(final BackupRequest request, final BackupResponse<T> response) { this.request = request; this.response = response; } public BackupRequest getRequest() { return request; } public BackupResponse<T> getResponse() { return response; } } }