/*
* Copyright (c) 2008-2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.zkutils;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import org.apache.zookeeper.server.persistence.FileTxnLog;
/**
* Handle commands about Zookeeper Txn logs
*/
public class ZkTxnHandler {
private static final Logger log = LoggerFactory.getLogger(ZkTxnHandler.class);
private String dataPath = "/data/zk/";
private String BACKUP_PREFIX = "backup.";
private int VERSION = 2;
private String version = "version-";
private File dataDir = null;
public ZkTxnHandler() {
}
/**
* Get last valid logged txn id.
*/
public long getLastValidZxid() {
dataDir = new File(dataPath, version + VERSION);
String sDataDir = dataDir.getAbsolutePath();
FileTxnLog txnLog = new FileTxnLog(dataDir);
// If there is corrupted txn before the last txn log file,
// txnLog.getLastLoggedZxid() would incorrectly return the 1st txn of the last txn log file.
// We could cover this ZK bug by moving the txnlog files (useless and already snapshoped) but the last.
File[] files = txnLog.getLogFiles(dataDir.listFiles(), 0);
if (files.length > 1) {
for (int i = 0; i < files.length - 1; i++) {
File targetFile = new File(sDataDir, BACKUP_PREFIX + files[i].getName());
files[i].renameTo(targetFile);
}
}
long lastValidZxid = txnLog.getLastLoggedZxid();
String tmpstr = String.format("last valid logged zxid:%s(hex)",
Long.toHexString(lastValidZxid));
log.info(tmpstr);
System.out.println(tmpstr);
return lastValidZxid;
}
/**
* Truncate to the specific txn.
*
* @param zxid The id(hex) of the txn to be truncated to
*/
public boolean truncateToZxid(String zxid) {
long lastValidZxid = getLastValidZxid();
long targetZxid = Long.parseLong(zxid, 16);
if (targetZxid < lastValidZxid) {
String errstr = String.format(
"It is not allowed to truncate to the txn %s(hex) which is prior to the last valid txn %s(hex)! It would lose data!",
Long.toHexString(targetZxid), Long.toHexString(lastValidZxid));
log.error(errstr);
System.out.println(errstr);
return false;
}
try {
dataDir = new File(dataPath, version + VERSION);
FileTxnLog truncLog = new FileTxnLog(dataDir);
truncLog.truncate(targetZxid);
truncLog.close();
System.out.println(String.format("Successfully truncated to zxid: %s(hex)",
Long.toHexString(targetZxid)));
} catch (IOException e) {
String errstr = String.format("Failed to truncated to zxid: %s(hex). Please check it manually.", Long.toHexString(targetZxid));
log.error(errstr);
System.out.println(errstr);
return false;
}
return true;
}
/**
* Truncate to the last valid logged txn.
*
* @param zxid The id of the last valid txn.
*/
public boolean truncateToZxid() {
return truncateToZxid(Long.toHexString(getLastValidZxid()));
}
}