package com.yahoo.dtf.actions.file;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import com.yahoo.dtf.exception.DTFException;
import com.yahoo.dtf.exception.ParseException;
import com.yahoo.dtf.recorder.Event;
/**
* @dtf.tag monitor_diff
*
* @dtf.since 1.0
* @dtf.author Rodney Gomes
*
* @dtf.tag.desc With this tag you can check which files were added since the
* moment you created the monitor.
*
* @dtf.event monitor_diff
* @dtf.event.attr newfiles
* @dtf.event.attr.desc List of all the new files.
*
* @dtf.tag.example
* <sequence>
* <monitor_create id="LOGS" file="tests/ut/output/.*"/>
* <sleep time="3s"/>
* <monitor_diff id="LOGS"/>
* <monitor_destroy id="LOGS"/>
*
* <createrange name="files" value="${monitor_diff.newfiles}"/>
* <for property="i" range="1..10">
* <log>new ${files}</log>
* </for>
* </sequence>
*/
public class Monitor_diff extends Monitor_create {
/**
* @dtf.attr update
* @dtf.attr.desc defines if we should move the current pointer in the file
* forward or if we should keep analyzing all files from the
* same point that we already picked at the beginning of the
* test. The default is to not update and stay at the same
* point since this allows for you to run multiple expressions
* against the same file. By setting this attribute to true
* you can move the files virtual "pointer" forward and keep
* checking only the latest data for changes.
*
*/
private String update = null;
/**
* Grabs the previous results and attaches any new files to the list of
* files that are to be monitored.
*
* @return
* @throws ParseException
* @throws IOException
*/
protected HashMap<String, DTFBufferedReader> getNewFiles()
throws ParseException, IOException {
HashMap<String, FileMonitor> monitors = getMonitors();
FileMonitor previous = monitors.get(getId());
HashMap<String, DTFBufferedReader> files = previous.getFiles();
HashMap<String, DTFBufferedReader> nfiles =
new HashMap<String, DTFBufferedReader>();
/*
* Now find files that have been created in this same directory
* after the monitor was started.
*/
File directory = previous.getDirectory();
final HashMap<String, DTFBufferedReader> filesFinal = files;
final String patternFinal = previous.getPattern();
File[] newfiles = directory.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
String file = dir.getAbsolutePath() + File.separatorChar + name;
return (!filesFinal.containsKey(file) &&
name.matches(patternFinal) &&
new File(dir,name).isFile());
}
});
// Add the previous files to the files HashMap so that then you can
// process the new files as well.
if ( newfiles != null ) {
for (int i = 0; i < newfiles.length; i++) {
DTFBufferedReader br = new DTFBufferedReader(newfiles[i],0);
nfiles.put(newfiles[i].getAbsolutePath(),br);
}
}
return nfiles;
}
public void execute() throws DTFException {
/*
* Retrieve what the state of each of the old files was, i.e. what their
* length was. So we can seek up to that length and then monitor for
* a grep expression beyond that point.
*
* Also remember to get the list of files that were created since then
* that still belong to the monitor so we can report on any matches
* within those files.
*/
try {
StringBuffer newfiles = new StringBuffer();
HashMap<String, DTFBufferedReader> files = getNewFiles();
Iterator<Entry<String,DTFBufferedReader>> entries =
files.entrySet().iterator();
while (entries.hasNext()) {
Entry<String,DTFBufferedReader> entry = entries.next();
newfiles.append(entry.getKey() + (entries.hasNext() ? "," : ""));
}
if ( !getUpdate() ) {
// we need to set the current set of files as the new base
// for this monitor
HashMap<String, FileMonitor> monitors = getMonitors();
FileMonitor previous = monitors.get(getId());
previous.replaceFiles(files);
}
Event event = new Event("monitor_diff");
event.start();
event.stop();
event.addAttribute("newfiles", newfiles.toString());
getRecorder().record(event);
} catch (FileNotFoundException e) {
throw new DTFException("Monitored file was deleted.", e);
} catch (IOException e) {
throw new DTFException("Monitored file failed to skip.", e);
}
}
public boolean getUpdate() throws ParseException { return toBoolean("update",update); }
public void setUpdate(String update) { this.update = update; }
}