package org.fastcatsearch.job.management;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.fastcatsearch.cluster.ClusterUtils;
import org.fastcatsearch.cluster.Node;
import org.fastcatsearch.cluster.NodeJobResult;
import org.fastcatsearch.cluster.NodeService;
import org.fastcatsearch.common.io.Streamable;
import org.fastcatsearch.control.JobService;
import org.fastcatsearch.control.ResultFuture;
import org.fastcatsearch.exception.FastcatSearchException;
import org.fastcatsearch.ir.IRService;
import org.fastcatsearch.ir.config.CollectionContext;
import org.fastcatsearch.ir.config.DataInfo.SegmentInfo;
import org.fastcatsearch.ir.io.DataInput;
import org.fastcatsearch.ir.io.DataOutput;
import org.fastcatsearch.job.Job;
import org.fastcatsearch.job.cluster.NodeCollectionReloadJob;
import org.fastcatsearch.job.indexing.TransferIndexFileMultiNodeJob;
import org.fastcatsearch.service.ServiceManager;
import org.fastcatsearch.util.FilePaths;
/**
* 지정한 source노드에서 dest 노드 리스트로 색인파일전파 및 리로드수행.
* */
public class CopyApplyIndexDataJob extends Job implements Streamable {
private static final long serialVersionUID = -5275884443430362098L;
private String collectionId;
private String sourceNodeId;
private List<String> destNodeIdList;
public CopyApplyIndexDataJob() {
}
public CopyApplyIndexDataJob(String collectionId, String sourceNodeId, List<String> destNodeIdList) {
this.collectionId = collectionId;
this.sourceNodeId = sourceNodeId;
this.destNodeIdList = destNodeIdList;
}
@Override
public void readFrom(DataInput input) throws IOException {
this.collectionId = input.readString();
this.sourceNodeId = input.readString();
int nodeSize = input.readInt();
this.destNodeIdList = new ArrayList<String>(nodeSize);
for (int i = 0; i < nodeSize; i++) {
destNodeIdList.add(input.readString());
}
}
@Override
public void writeTo(DataOutput output) throws IOException {
output.writeString(collectionId);
output.writeString(sourceNodeId);
output.writeInt(destNodeIdList.size());
for (int i = 0; i < destNodeIdList.size(); i++) {
output.writeString(destNodeIdList.get(i));
}
}
@Override
public JobResult doRun() throws FastcatSearchException {
NodeService nodeService = ServiceManager.getInstance().getService(NodeService.class);
Node sourceNode = nodeService.getNodeById(sourceNodeId);
if(nodeService.isMyNode(sourceNode)){
List<Node> destNodeList = nodeService.getNodeById(destNodeIdList);
IRService irService = ServiceManager.getInstance().getService(IRService.class);
CollectionContext collectionContext = irService.collectionContext(collectionId);
FilePaths indexFilePaths = collectionContext.indexFilePaths();
File indexDir = indexFilePaths.file();
// SegmentInfo segmentInfo = collectionContext.dataInfo().getLastSegmentInfo();
// if (segmentInfo != null) {
NodeJobResult[] nodeResultList = null;
// String segmentId = segmentInfo.getId();
logger.debug("Transfer index data collection[{}] >> {}", collectionId, indexDir.getAbsolutePath());
// 색인된 Segment 파일전송.
TransferIndexFileMultiNodeJob transferJob = new TransferIndexFileMultiNodeJob(indexDir, destNodeList);
ResultFuture resultFuture = JobService.getInstance().offer(transferJob);
Object obj = resultFuture.take();
if(resultFuture.isSuccess() && obj != null){
nodeResultList = (NodeJobResult[]) obj;
}else{
}
//성공한 node만 전송.
ArrayList<Node> nodeList = new ArrayList<Node>();
for (int i = 0; i < nodeResultList.length; i++) {
NodeJobResult r = nodeResultList[i];
logger.debug("node#{} >> {}", i, r);
if (r.isSuccess()) {
nodeList.add(r.node());
}else{
logger.warn("Do not send index file to {}", r.node());
}
}
/*
* 데이터노드에 컬렉션 리로드 요청.
*/
NodeCollectionReloadJob reloadJob = new NodeCollectionReloadJob(collectionContext);
nodeResultList = ClusterUtils.sendJobToNodeList(reloadJob, nodeService, nodeList, false);
for (int i = 0; i < nodeResultList.length; i++) {
NodeJobResult r = nodeResultList[i];
logger.debug("node#{} >> {}", i, r);
if (r.isSuccess()) {
logger.info("{} Collection reload OK.", r.node());
}else{
logger.warn("{} Collection reload Fail.", r.node());
}
}
// }
}else{
nodeService.sendRequest(sourceNode, this);
}
return new JobResult(true);
}
}