blob: 5cb73c91394da755690e1bda17840a4e6115a782 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.raid;
import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.LinkedList;
import org.apache.hadoop.util.LineReader;
import org.apache.hadoop.io.Text;
/**
* Represents the contents of a HAR Index file. The HAR is assumed to be
* comprising of RAID parity files only and no directories.
*/
public class HarIndex {
public static final String indexFileName = "_index";
private List<IndexEntry> entries = new LinkedList<IndexEntry>();
/**
* Represents information in a single line of the HAR index file.
*/
public static class IndexEntry {
String fileName; // Name of the file in the part file.
long startOffset; // Start offset within the part file.
long length; // Length of this file within the part file.
long mtime; // Modification time of the file.
String partFileName; // Name of the part file.
IndexEntry(String fileName, long startOffset, long length,
long mtime, String partFileName) {
this.fileName = fileName;
this.startOffset = startOffset;
this.length = length;
this.mtime = mtime;
this.partFileName = partFileName;
}
public String toString() {
return "fileName=" + fileName +
", startOffset=" + startOffset +
", length=" + length +
", mtime=" + mtime +
", partFileName=" + partFileName;
}
}
/**
* Constructor that reads the contents of the index file.
* @param in An input stream to the index file.
* @param max The size of the index file.
* @throws IOException
*/
public HarIndex(InputStream in, long max) throws IOException {
LineReader lineReader = new LineReader(in);
Text text = new Text();
long nread = 0;
while (nread < max) {
int n = lineReader.readLine(text);
nread += n;
String line = text.toString();
try {
parseLine(line);
} catch (UnsupportedEncodingException e) {
throw new IOException("UnsupportedEncodingException after reading " +
nread + "bytes");
}
}
}
/**
* Parses each line and extracts relevant information.
* @param line
* @throws UnsupportedEncodingException
*/
void parseLine(String line) throws UnsupportedEncodingException {
String[] splits = line.split(" ");
boolean isDir = "dir".equals(splits[1]) ? true: false;
if (!isDir && splits.length >= 6) {
String name = URLDecoder.decode(splits[0], "UTF-8");
String partName = URLDecoder.decode(splits[2], "UTF-8");
long startIndex = Long.parseLong(splits[3]);
long length = Long.parseLong(splits[4]);
String[] newsplits = URLDecoder.decode(splits[5],"UTF-8").split(" ");
if (newsplits != null && newsplits.length >= 4) {
long mtime = Long.parseLong(newsplits[0]);
IndexEntry entry = new IndexEntry(
name, startIndex, length, mtime, partName);
entries.add(entry);
}
}
}
/**
* Finds the index entry corresponding to a HAR partFile at an offset.
* @param partName The name of the part file (part-*).
* @param partFileOffset The offset into the part file.
* @return The entry corresponding to partName:partFileOffset.
*/
public IndexEntry findEntry(String partName, long partFileOffset) {
for (IndexEntry e: entries) {
boolean nameMatch = partName.equals(e.partFileName);
boolean inRange = (partFileOffset >= e.startOffset) &&
(partFileOffset < e.startOffset + e.length);
if (nameMatch && inRange) {
return e;
}
}
return null;
}
/**
* Finds the index entry corresponding to a file in the archive
*/
public IndexEntry findEntryByFileName(String fileName) {
for (IndexEntry e: entries) {
if (fileName.equals(e.fileName)) {
return e;
}
}
return null;
}
}