package com.neverwinterdp.scribengin.commitlog; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.URI; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collections; import java.util.ListIterator; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.log4j.Logger; public class ScribeCommitLog { private static final int NUM_CORRECT_RECORDS = 3; private static final Logger log = Logger.getLogger(ScribeCommitLog.class); private FileSystem fs; //private List recentLogEntryList; private ListIterator<ScribeLogEntry> recentLogIter; private Path path; public ScribeCommitLog(String uri) throws IOException { this(uri, false); } public ScribeCommitLog(String uri, boolean useLocalFS) throws IOException { Configuration conf; path = new Path(uri); //if (useLocalFS == false) { // hdfs conf = new Configuration(); conf.addResource(new Path("/etc/hadoop/conf/hdfs-site.xml")); conf.addResource(new Path("/etc/hadoop/conf/core-site.xml")); conf.addResource(new Path("/etc/hadoop/conf/yarn-site.xml")); conf.addResource(new Path("/etc/hadoop/conf/mapred-site.xml")); fs = FileSystem.get(URI.create(uri), conf); //} else { // local // It's unit test's responsiblility to set fs. //} } public void record(long startOffset, long endOffset, String srcPath, String destPath) throws NoSuchAlgorithmException, IOException { FSDataOutputStream os = null; //appending doesn't work //So read in old file //Write out new file if (fs.exists(path)) { //this append nonsense doesn't work //os = fs.append(path); //read in the old log BufferedReader br=new BufferedReader(new InputStreamReader(fs.open(path))); String finalLine=""; String line=br.readLine(); finalLine += line; while (line != null){ line = br.readLine(); finalLine += line; } os = fs.create(path); if(finalLine != null && !finalLine.isEmpty()){ os.write(finalLine.getBytes()); ScribeLogEntry entry = new ScribeLogEntry(startOffset, endOffset, srcPath, destPath); String jsonStr = ScribeLogEntry.toJson(entry); os.write(jsonStr.getBytes()); os.write('\n'); } } //Create the new file else { os = fs.create(path); ScribeLogEntry entry = new ScribeLogEntry(startOffset, endOffset, srcPath, destPath); String jsonStr = ScribeLogEntry.toJson(entry); os.write(jsonStr.getBytes()); os.write('\n'); } //close if(os != null){ try { os.close(); } catch (IOException e) { log.error(e.getMessage()); e.printStackTrace(); } //fsClose(); } } public void read() throws IOException { ArrayList<ScribeLogEntry> logEntryList = new ArrayList<ScribeLogEntry>(); if (fs.exists(path)) { FileStatus status = fs.getFileStatus(path); long fptr = status.getLen() - 1; FSDataInputStream in = fs.open(path); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int correctEntryCnt = 0; System.out.println(">>fptr : " + fptr); //xxx while (fptr >= 0) { in.seek(fptr); byte b = in.readByte(); if (b != '\n') { buffer.write(b); } if (b == '\n' || fptr == 0) { if (buffer.size() > 0) { // read from the back of the file, so we'll have to reverse the string. String jsonStr = new StringBuffer(buffer.toString()).reverse().toString(); buffer.reset(); //TODO: log the jsonStr's content System.out.println(">> jsonStr: " + jsonStr); //xxx ScribeLogEntry e = ScribeLogEntry.fromJson(jsonStr); logEntryList.add(e); try { if (e.isCheckSumValid()) { correctEntryCnt++; } } catch (NoSuchAlgorithmException ex) { //TODO: log } if (correctEntryCnt == NUM_CORRECT_RECORDS) { break; } } } fptr--; } //while // Check to see if the last character is '\n' // If not, make sure to write an extra '\n' to the log file in.seek(status.getLen() - 1); if (in.readByte() != '\n') { FSDataOutputStream os = fs.append(path); os.write('\n'); try { os.close(); } catch (IOException e) { //TODO: log } } //fsClose(); } Collections.reverse(logEntryList); recentLogIter = logEntryList.listIterator(logEntryList.size()); } // return null, if there's no more entry in the log public ScribeLogEntry getLatestEntry() { ScribeLogEntry r = null; if (recentLogIter.hasPrevious()) { r = recentLogIter.previous(); } return r; } public void fsClose() { try { fs.close(); } catch (IOException e) { log.error(e.getMessage()); e.printStackTrace(); } } /** * Clear the contents of the commit log. * * */ public void clear() throws IOException { // fs.truncate(path); System.out.println("DELETING LOG "+path.toString()); fs.delete(path, true); while(fs.exists(path)){} System.out.println("DELETING LOG COMPLETE"); //fsClose(); } }