/**
* Copyright 2016, Xiaomi.
* All rights reserved.
* Author: xiajun@xiaomi.com
*/
package com.xiaomi.infra.galaxy.lcs.log.core.file;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import com.xiaomi.infra.galaxy.lcs.log.core.ILogger;
import com.xiaomi.infra.galaxy.lcs.log.core.transaction.Transaction;
import com.xiaomi.infra.galaxy.talos.client.serialization.MessageSerialization;
import com.xiaomi.infra.galaxy.talos.thrift.Message;
public class LCSFileReader extends Transaction<List<Message>> {
private ILogger logger;
private String topicName;
private String rootFilePath;
private String topicFilePath;
private String curFilePath;
public LCSFileReader(ILogger logger, String topicName, String rootFilePath) {
this.logger = logger;
this.topicName = topicName;
this.rootFilePath = rootFilePath;
}
@Override
protected void doInitTransaction() {
if (rootFilePath.isEmpty()) {
throw new RuntimeException("please set rootFilePath");
}
if (!rootFilePath.startsWith("/")) {
throw new RuntimeException("please set rootFilePath as the absolute file path");
}
File file = new File(rootFilePath);
if (!file.exists()) {
throw new RuntimeException("please make sure rootFilePath: " + rootFilePath + " exist");
}
topicFilePath = FileUtils.formatTopicFilePath(rootFilePath, topicName);
}
@Override
protected void doStartTransaction() {
TreeMap<String, File> fileTreeMap = FileUtils.listFile(topicFilePath, topicName);
if (!fileTreeMap.isEmpty()) {
curFilePath = fileTreeMap.firstEntry().getValue().getAbsolutePath();
} else {
curFilePath = null;
}
}
@Override
protected List<Message> doTake() {
List<Message> messageList = new ArrayList<Message>();
if (curFilePath == null) {
return messageList;
}
try {
FileInputStream fileInputStream = new FileInputStream(curFilePath);
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
while (true) {
try {
Message message = MessageSerialization.deserializeMessage(dataInputStream);
messageList.add(message);
} catch (EOFException e) {
logger.debug("Topic: " + topicName + " read [" + messageList.size() +
"] messages from file: " + curFilePath);
break;
} catch (IOException e) {
logger.error("Topic: " + topicName + " readMessage failed from " +
"filePath: " + curFilePath +" after read [" + messageList.size() +
"] messages, we just skip the other message in this file", e);
}
}
} catch (FileNotFoundException e) {
logger.error("Topic: " + topicName + " filePath: " + curFilePath + " not exist", e);
throw new RuntimeException("readMessage from " + curFilePath +
" while it not exist", e);
}
return messageList;
}
@Override
protected void doCommitTransaction() {
if (curFilePath != null) {
try {
FileUtils.deleteFile(curFilePath);
logger.info("Topic: " + topicName + " delete curFile: " + curFilePath +
" success after read all it's messages");
} catch (FileNotFoundException e) {
logger.error("Topic: " + topicName + " delete curFile: " + curFilePath +
" while it not exist", e);
} catch (IOException e) {
logger.error("Topic: " + topicName + " delete curFile: " + curFilePath +
" failed, the message in this file will send to talos again", e);
}
}
curFilePath = null;
}
@Override
protected void doRollbackTransaction() {
if (curFilePath != null) {
logger.error("Topic: " + topicName + " rollbackTransaction for file: " + curFilePath);
}
curFilePath = null;
}
@Override
protected void doCloseTransaction() {
}
}