Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format the StoragePlugin related files #287

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@
* This is a special kind of comparison function meant for a combo binary/linear search function.
* This takes in a byte sequence (perhaps from a PB file) and compares it to the point (timestamp) being sought.
* It then returns one of the enums to direct the direction of search.
* We assume that time is from the left (past) to the right (future).
* We assume that time is from the left (past) to the right (future).
* @author mshankar
*/
public interface CompareEventLine {
enum NextStep {
GO_LEFT,
GO_RIGHT,
STAY_WHERE_YOU_ARE
}
/**
* This is the actual comparison function.
* @param line1 - A full PB line
* @param line2 - A full PB line
* @return NextStep one of the eumuration of NextStep
* @throws IOException  
*/
public NextStep compare(byte[] line1, byte[] line2) throws IOException;
enum NextStep {
GO_LEFT,
GO_RIGHT,
STAY_WHERE_YOU_ARE
}

/**
* This is the actual comparison function.
* @param line1 - A full PB line
* @param line2 - A full PB line
* @return NextStep one of the eumuration of NextStep
* @throws IOException  
*/
public NextStep compare(byte[] line1, byte[] line2) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.nio.file.Files;
import java.nio.file.Path;


/**
* This is a variant of binary search that searches for an event in a event stream file.
* We assume a time-sorted PB file separated by unix newlines as outlined in the archiver appliance design doc.
Expand All @@ -31,175 +30,174 @@
* <li>LineByteStream.readLine's after this should give events that satisfy getData's requirements.</li>
* <li>Remember to terminate appropriately</li>
* </ol>
*
*
* @author mshankar
*
*/
public class FileEventStreamSearch {
private static final Logger logger = LogManager.getLogger(FileEventStreamSearch.class);
/**
* Constant use to bound length of searches before giving up.
*/
private static final int MAXITERATIONS = 1000;
/**
* Internally used to indicate the left/lower window for the search
*/
private long min = 0;
/**
* Internally used to indicate the right/upper window for the search
*/
private long max = 0;
/**
* Internally used to the current search point
*/
private long mid = 0;
/**
* Remember the last left/lower bound; this is the requirement for getData when the time t1 is not present exactly in the file.
*/
private long lastgoright = 0;
private Path path;

/**
* Position where we found the value
*/
private long foundPosition = 0;

/**
* PB files often have a header; so we'd want to start after the header.
*/
private long startPosition = 0;


/**
* @param path Path
* @param startPosn a starting position of search PB files
*/
public FileEventStreamSearch(Path path, long startPosn) {
this.path = path;
this.startPosition = startPosn;
}
private static final Logger logger = LogManager.getLogger(FileEventStreamSearch.class);
/**
* Constant use to bound length of searches before giving up.
*/
private static final int MAXITERATIONS = 1000;
/**
* Internally used to indicate the left/lower window for the search
*/
private long min = 0;
/**
* Internally used to indicate the right/upper window for the search
*/
private long max = 0;
/**
* Internally used to the current search point
*/
private long mid = 0;
/**
* Remember the last left/lower bound; this is the requirement for getData when the time t1 is not present exactly in the file.
*/
private long lastgoright = 0;

private Path path;

/**
* Position where we found the value
*/
private long foundPosition = 0;

/**
* PB files often have a header; so we'd want to start after the header.
*/
private long startPosition = 0;

/**
* @param path Path
* @param startPosn a starting position of search PB files
*/
public FileEventStreamSearch(Path path, long startPosn) {
this.path = path;
this.startPosition = startPosn;
}

public long getFoundPosition() {
return foundPosition;
}

/**
* Set the fileChannels position to a point that best satisfies the requirements for getData(t1,...).
* If found (return value is true), the file's position is set such that
* <code>
* LineByteStream lis = new LineByteStream(fchannel);
* lis.seekToFirstNewLine();
* byte[] line = lis.readLine();
* </code>
* starts returning events that satisfy getData's requirements
* @return <code>true</code> or <code>false</code>
* @param dbrtype ArchDBRType the enumeration type
* @param yearSecondTimestamp Search seconds into year
* @throws IOException &emsp;
* @see edu.stanford.slac.archiverappliance.PlainPB.ComparePBEvent
*/
public boolean seekToTime(ArchDBRTypes dbrtype, YearSecondTimestamp yearSecondTimestamp) throws IOException {
ComparePBEvent comparefunction = new ComparePBEvent(dbrtype, yearSecondTimestamp);
return seekToTime(comparefunction);
}

/**
* This should only be used by the unit tests.
* @param comparefunction CompareEventLine
* @return <code>true</code> or <code>false</code>
* @throws IOException when parsing the absolute path
*/
public boolean seekToTime(CompareEventLine comparefunction) throws IOException {
boolean found = binarysearch(comparefunction);
if (found) {
// We found an exact match.
return true;
} else {
// We did not find an exact match.
// However, check to see if the location satisfies s1 <= t1 < s2
if (lastgoright == 0 && startPosition != 0) {
// Skip the header if any specified.
lastgoright = startPosition;
}
try (LineByteStream lis = new LineByteStream(path, lastgoright)) {
long currPosn = lis.getCurrentPosition();
try {
lis.seekToFirstNewLine();
byte[] line1 = lis.readLine();
byte[] line2 = lis.readLine();
if (line1 == null || line2 == null || line1.length == 0 || line2.length == 0) {
// Nope, we did not find anything.
return false;
} else {
CompareEventLine.NextStep test = comparefunction.compare(line1, line2);
// For s1 < t1, the compare function should tell us to go right.
// For s1 == t1, it should tell us to stay where we are.
// for t1 < s2, the compare function should tell us to go left.
if (test == CompareEventLine.NextStep.STAY_WHERE_YOU_ARE) {
// We found a location that satisfies s1 <= t1 < s2
foundPosition = lastgoright;
return true;
} else {
// In this case, we really did not find the event as it is out of range.
return false;
}
}
} catch (IOException ex) {
logger.error("Exception when parsing " + lis.getAbsolutePath() + " near posn " + currPosn, ex);
throw ex;
}
}
}
}

private boolean binarysearch(CompareEventLine comparefunction) throws IOException {
// We bound the binary search to avoid infinite loops.
int maxIterations = MAXITERATIONS;
try {
// Set up binary search.
min = this.startPosition;
max = Files.size(path) - 1;
do {
mid = min + ((max - min) / 2);
// System.out.println("Min: " + min + " Mid: " + mid + " Max: " + max);
try (LineByteStream lis = new LineByteStream(path, mid)) {
lis.seekToFirstNewLine();
byte[] line1 = lis.readLine();
if (line1 == null || line1.length <= 0) {
// Empty line in the PB file - Returning false from search.
return false;
}
byte[] line2 = lis.readLine();

CompareEventLine.NextStep nextStep = comparefunction.compare(line1, line2);
switch (nextStep) {
case GO_LEFT:
max = mid - 1;
break;
case GO_RIGHT:
lastgoright = mid;
min = mid + 1;
break;
case STAY_WHERE_YOU_ARE:
foundPosition = mid;
return true;
default:
logger.error("Compare function returned something unexpeected " + nextStep);
}

public long getFoundPosition() {
return foundPosition;
}


/**
* Set the fileChannels position to a point that best satisfies the requirements for getData(t1,...).
* If found (return value is true), the file's position is set such that
* <code>
* LineByteStream lis = new LineByteStream(fchannel);
* lis.seekToFirstNewLine();
* byte[] line = lis.readLine();
* </code>
* starts returning events that satisfy getData's requirements
* @return <code>true</code> or <code>false</code>
* @param dbrtype ArchDBRType the enumeration type
* @param yearSecondTimestamp Search seconds into year
* @throws IOException &emsp;
* @see edu.stanford.slac.archiverappliance.PlainPB.ComparePBEvent
*/
public boolean seekToTime(ArchDBRTypes dbrtype, YearSecondTimestamp yearSecondTimestamp) throws IOException {
ComparePBEvent comparefunction = new ComparePBEvent(dbrtype, yearSecondTimestamp);
return seekToTime(comparefunction);
}


/**
* This should only be used by the unit tests.
* @param comparefunction CompareEventLine
* @return <code>true</code> or <code>false</code>
* @throws IOException when parsing the absolute path
*/
public boolean seekToTime(CompareEventLine comparefunction) throws IOException {
boolean found = binarysearch(comparefunction);
if(found) {
// We found an exact match.
return true;
} else {
// We did not find an exact match.
// However, check to see if the location satisfies s1 <= t1 < s2
if(lastgoright == 0 && startPosition != 0) {
// Skip the header if any specified.
lastgoright = startPosition;
}
try(LineByteStream lis = new LineByteStream(path, lastgoright)) {
long currPosn = lis.getCurrentPosition();
try {
lis.seekToFirstNewLine();
byte[] line1 = lis.readLine();
byte[] line2 = lis.readLine();
if(line1 == null || line2 == null || line1.length == 0 || line2.length == 0) {
// Nope, we did not find anything.
return false;
} else {
CompareEventLine.NextStep test = comparefunction.compare(line1, line2);
// For s1 < t1, the compare function should tell us to go right.
// For s1 == t1, it should tell us to stay where we are.
// for t1 < s2, the compare function should tell us to go left.
if(test == CompareEventLine.NextStep.STAY_WHERE_YOU_ARE) {
// We found a location that satisfies s1 <= t1 < s2
foundPosition = lastgoright;
return true;
} else {
// In this case, we really did not find the event as it is out of range.
return false;
}
}
} catch(IOException ex) {
logger.error("Exception when parsing " + lis.getAbsolutePath() + " near posn " + currPosn, ex);
throw ex;
}
}
}
}

private boolean binarysearch(CompareEventLine comparefunction) throws IOException {
// We bound the binary search to avoid infinite loops.
int maxIterations = MAXITERATIONS;
try {
// Set up binary search.
min = this.startPosition;
max = Files.size(path)-1;
do {
mid = min + ((max - min)/2);
// System.out.println("Min: " + min + " Mid: " + mid + " Max: " + max);
try(LineByteStream lis = new LineByteStream(path, mid)) {
lis.seekToFirstNewLine();
byte[] line1 = lis.readLine();
if(line1 == null || line1.length <= 0) {
// Empty line in the PB file - Returning false from search.
return false;
}
byte[] line2 = lis.readLine();
maxIterations--;
}
} while ((max > min) && maxIterations > 0);
} catch (Exception ex) {
throw new IOException(
"Exception searching in input stream; min: " + min + " mid: " + mid + " max:" + max, ex);
}

CompareEventLine.NextStep nextStep = comparefunction.compare(line1, line2);
switch(nextStep) {
case GO_LEFT:
max = mid - 1;
break;
case GO_RIGHT:
lastgoright = mid;
min = mid + 1;
break;
case STAY_WHERE_YOU_ARE:
foundPosition = mid;
return true;
default:
logger.error("Compare function returned something unexpeected " + nextStep);
}
if (maxIterations <= 0) {
throw new IOException("Max iterations reached");
}

maxIterations--;
}
} while((max > min) && maxIterations > 0);
} catch(Exception ex) {
throw new IOException("Exception searching in input stream; min: " + min + " mid: " + mid + " max:" + max, ex);
}

if(maxIterations <= 0) {
throw new IOException("Max iterations reached");
}

return false;
}
return false;
}
}
Loading
Loading