Hello,
I am having problems trying to "tail" an existing file.
When the file is being written into, I can tail it without any problem.
The problem rises when the file is already complete, and I try to open it.
I tried to make a small demo program but for some reason I am unable to get the demo program to give the same behaviour.
Below is the class in which it all goes wrong.
I basically opens the file usring RandomAccessfile.
when I try to retrieve the length of the file a bit further, my ascii file I am viewing already changed to .nfs01231353434 something.
But all gets displayed ok.
When I then close the text pane in which this tail class is logging, the file itself is deleted.
As this has something to do with NFS here is the setup :
The java jar file is located on a remote solaris disk, so is the ASCII file I am trying to view.
The local machine where I am running my application is Red Hat Linux 3.2.3-52.
Apologies if this information is kinda vague but as I am unable to supply a demo program, I dont know else how to explain my problem.
The class that does the "tailing"
package com.alcatel.tamtam.main;
import java.io.*;
import java.util.*;
public class Usr_LogFileTrailer extends Thread
{
/**
* How frequently to check for file changes; defaults to 5 seconds
*/
private long sampleInterval = 5000;
/**
* Number of lines in a row we output, otherwise problems with large files
*/
private int lineBuffer = 250;
/**
* The log file to tail
*/
private File logfile;
/**
* Defines whether the log file tailer should include the entire contents
* of the exising log file or tail from the end of the file when the tailer starts
*/
private boolean startAtBeginning = false;
/**
* Is the tailer currently tailing ?
*/
private boolean tailing = false;
/**
* Is the thread suspended or not ?
*/
private boolean threadSuspended = true;
/**
* File pointer where thread last logged a line
*/
private long filePointer = 0;
/**
* Set of listeners
*/
private Set listeners = new HashSet();
/**
* Creates a new log file tailer that tails an existing file and checks the file for
* updates every 5000ms
*/
public Usr_LogFileTrailer( File file )
{
this.logfile = file;
}
/**
* Creates a new log file tailer
*
* @param file The file to tail
* @param sampleInterval How often to check for updates to the log file (default = 5000ms)
* @param startAtBeginning Should the tailer simply tail or should it process the entire
* file and continue tailing (true) or simply start tailing from the
* end of the file
*/
public Usr_LogFileTrailer( File file, long sampleInterval, boolean startAtBeginning )
{
this.logfile = file;
this.sampleInterval = sampleInterval;
setPriority(Thread.MIN_PRIORITY);
}
public void addLogFileTailerListener( Usr_LogFileTrailerListener l )
{
this.listeners.add( l );
}
public void removeLogFileTailerListener( Usr_LogFileTrailerListener l )
{
this.listeners.remove( l );
}
/*
*
* Methods to trigger our event listeners
*
*/
protected void fireNewLogFileLine( String line )
{
for( Iterator i=this.listeners.iterator(); i.hasNext(); )
{
Usr_LogFileTrailerListener l = ( Usr_LogFileTrailerListener )i.next();
l.newLogFileLine( line );
}
}
public void stopTailing()
{
this.tailing = false;
}
public void restart()
{
filePointer = 0;
}
public synchronized void setSuspended(boolean threadSuspended)
{
this.threadSuspended = threadSuspended;
if ( ! threadSuspended ) notify();
}
public void run()
{
try
{
while ( ! logfile.exists() )
{
synchronized(this)
{
while ( threadSuspended ) wait();
}
Thread.currentThread().sleep(1000);
File parentDir = logfile.getParentFile();
if ( parentDir.exists() && parentDir.isDirectory() )
{
File[] parentFiles = parentDir.listFiles();
for ( File parentFile : parentFiles )
{
if ( parentFile.getName().equals(logfile.getName()) ||
parentFile.getName().startsWith(logfile.getName() + "_child") )
{
logfile = parentFile;
break;
}
}
}
}
}
catch(InterruptedException iEx)
{
iEx.printStackTrace();
}
// Determine start point
if( this.startAtBeginning )
{
filePointer = 0;
}
try
{
// Start tailing
this.tailing = true;
RandomAccessFile file = new RandomAccessFile( logfile, "r" );
while( this.tailing )
{
synchronized(this)
{
while ( threadSuspended ) wait();
}
try
{
// Compare the length of the file to the file pointer
// long fileLength = 0;
//long fileLength = file.length();
long fileLength = this.logfile.length();
if( fileLength < filePointer )
{
// Log file must have been rotated or deleted;
// reopen the file and reset the file pointer
file = new RandomAccessFile( logfile, "r" );
filePointer = 0;
}
if( fileLength > filePointer )
{
// There is data to read
file.seek( filePointer );
String line = file.readLine();
int lineCount = 0;
// this.fireBlockTextPane();
while( line != null && lineCount < lineBuffer)
{
this.fireNewLogFileLine( line );
line = file.readLine();
lineCount++;
}
filePointer = file.getFilePointer();
this.fireFlushLogging();
// this.fireNewTextPaneUpdate();
}
// Sleep for the specified interval
sleep( this.sampleInterval );
}
catch( Exception e )
{
e.printStackTrace();
}
}
// Close the file that we are tailing
file.close();
}
catch( Exception e )
{
e.printStackTrace();
}
}
}