package org.fastcatsearch.task;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.fastcatsearch.cluster.Node;
import org.fastcatsearch.cluster.NodeService;
import org.fastcatsearch.env.Environment;
import org.fastcatsearch.exception.FastcatSearchException;
import org.fastcatsearch.transport.TransportException;
import org.fastcatsearch.transport.common.SendFileResultFuture;
import org.fastcatsearch.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class IndexFileTransfer {
private static Logger logger = LoggerFactory.getLogger(IndexFileTransfer.class);
private Environment environment;
public IndexFileTransfer(Environment environment) {
this.environment = environment;
}
// 세그먼트를 전송한다.
public boolean[] transferDirectory(File directory, NodeService nodeService, List<Node> nodeList) throws FastcatSearchException {
boolean[] resultList = new boolean[nodeList.size()];
logger.debug("tranferDirectory >> {}", directory.getAbsolutePath());
Collection<File> files = FileUtils.listFiles(directory, null, true);
int totalFileCount = files.size();
// TODO 순차적전송을 개선하여 더 빠른 방법을 찾아보자.
OUTTER:
for (int i = 0; i < nodeList.size(); i++) {
Node node = nodeList.get(i);
if(!node.isActive()){
continue;
}
if (nodeService.isMyNode(node)) {
// 자신에게는 전송하지 않는다.
continue;
}
logger.debug("Send File Nodes [{} / {}] {}", new Object[] { i + 1, nodeList.size(), node });
Iterator<File> fileIterator = files.iterator();
int fileCount = 1;
while (fileIterator.hasNext()) {
File sourceFile = fileIterator.next();
File relativeFile = environment.filePaths().relativise(sourceFile);
logger.info("[{} / {}]파일 {} 전송시작! ", new Object[] { fileCount, totalFileCount, sourceFile.getPath() });
SendFileResultFuture sendFileResultFuture;
try {
sendFileResultFuture = nodeService.sendFile(node, sourceFile, relativeFile);
} catch (TransportException e) {
logger.error("Transport exception sending {} to {} : {}", sourceFile.getName(), node, e);
continue OUTTER; //다음노드로.
}
if (sendFileResultFuture != null) {
Object result = sendFileResultFuture.take();
if (sendFileResultFuture.isSuccess()) {
logger.info("[{} / {}]파일 {} 전송완료!", new Object[] { fileCount, totalFileCount, relativeFile.getPath() });
} else {
logger.error("Fail to send {} to {} : {}", sourceFile.getName(), node);
continue OUTTER; //다음노드로.
}
} else {
// null이라면 디렉토리 또는 동일노드..
logger.warn("skip file {} to {}", sourceFile.getName(), node);
continue; //다음파일로...
}
fileCount++;
}
resultList[i] = true;
}
return resultList;
}
public void transferFile(File file, NodeService nodeService, Node node) throws TransportException {
Collection<File> files = null;
if(!file.exists()){
//not exists.
throw new TransportException("File is not exist. "+file.getAbsolutePath());
}else if(file.isDirectory()){
files = FileUtils.listFiles(file, null, true);
}else{
files = new HashSet<File>();
files.add(file);
}
int totalFileCount = files.size();
Iterator<File> fileIterator = files.iterator();
int fileCount = 1;
while (fileIterator.hasNext()) {
File sourceFile = fileIterator.next();
File relativeFile = environment.filePaths().relativise(sourceFile);
logger.info("[{} / {}]파일 {} 전송시작! ", new Object[] { fileCount, totalFileCount, sourceFile.getPath() });
SendFileResultFuture sendFileResultFuture = null;
try {
sendFileResultFuture = nodeService.sendFile(node, sourceFile, relativeFile);
} catch (TransportException e) {
logger.error("Transport exception sending {} to {} : {}", sourceFile.getName(), node, e);
throw e;
}
if (sendFileResultFuture != null) {
logger.debug("파일전송 결과대기.");
Object result = sendFileResultFuture.take();
logger.debug("파일전송 결과받음 >> {}", result);
if (sendFileResultFuture.isSuccess()) {
logger.info("[{} / {}]파일 {} 전송완료!", new Object[] { fileCount, totalFileCount, relativeFile.getPath() });
} else {
logger.error("Fail to send {} to {} : {}", sourceFile.getName(), node);
throw new TransportException("Fail to send file "+sourceFile.getName());
}
} else {
// null이라면 디렉토리 또는 동일노드..
logger.warn("skip file {} to {}", sourceFile.getName(), node);
continue; //다음파일로...
}
fileCount++;
}
}
}