📄 fileexpirationservice.java
字号:
LOG.debug( ": " + TimeUtils.toRelativeTimeMillis(expiresAt) + " " + file.getCanonicalPath() );
*/
break;
default:
if (LOG.isEnabledFor(Priority.INFO))
LOG.warn( "Unexpected Action in log write. Writing anyway." );
}
if( null == out )
throw new IOException( "out file is unavailable" );
synchronized( out ) {
out.writeInt ( action );
out.writeUTF ( file.getCanonicalPath() );
out.writeLong ( expiresAt );
out.writeLong ( cacheLifetime );
outFD.sync();
mods++;
}
}
// This is never executed in parallel, so it does not need to synch
// what only compress touches (db, tmpDb).
private void compress( boolean removeunknowns ) throws IOException {
DataInputStream in = null;
long start = TimeUtils.timeNow();
// if the output stream is open, close it
if (out != null) {
out.flush(); outFD.sync();
out.close();
out = null;
outFD = null;
}
int oldmod = mods;
mods = 0;
if (tmpDb.exists())
tmpDb.delete();
if (tmpDb.exists())
throw new IOException( "Could not remove existing temporary db." );
// open an input stream to read existing log
// open an output stream to a temporary file
// compress input stream into output stream
try {
in = new DataInputStream(new BufferedInputStream(new FileInputStream(db)));
openlog( tmpDb, false );
if (LOG.isEnabledFor(Priority.INFO)) {
LOG.info("Expiration log compression begins." );
}
compressStreams(in);
} catch( IOException compressFailed ) {
if (LOG.isEnabledFor(Priority.WARN))
LOG.warn("Expiration log compression failed.", compressFailed );
throw compressFailed;
} finally {
// make sure we close all streams
if (in != null)
try {
in.close();
in = null;
} catch (IOException e) {}
if (out != null) {
try {
out.flush(); outFD.sync();
out.close();
out = null;
outFD = null;
} catch (IOException e) {}
}
if ( tmpDb.exists() && db.exists() ) { // an existing file will prevent rename on win2k!
if( !db.delete() ) {
if (LOG.isEnabledFor(Priority.WARN))
LOG.warn("could not delete old db. this will be a problem." );
}
}
else {
if (LOG.isEnabledFor(Priority.WARN))
LOG.warn("Either db or tmpdb was missing!" );
}
if ( tmpDb.exists() && !db.exists() ) {
if( !tmpDb.renameTo(db) && LOG.isEnabledFor(Priority.WARN) ) // if we deleted but rename failed, oh well
LOG.warn("Could not rename temporary db to db file" );
} else {
if (LOG.isEnabledFor(Priority.WARN))
LOG.warn("Could not rename temporary log to log file, files missing or in the way." );
}
openlog( db, true );
}
if (LOG.isEnabledFor(Priority.INFO)) {
LOG.info("Compressed " + db + " of " + hash.size() + " records." +
"\n\t Compressed " + oldmod + " log entries to " + mods + " log entries." +
"\n\t Compressed in " + TimeUtils.toRelativeTimeMillis(TimeUtils.timeNow(), start) + " ms." );
}
/*
// display the list of files being managed.
synchronized( this ) {
Enumeration allExpires = hash.elements();
StringBuffer fileList = new StringBuffer();
fileList.append( "Expiration controlled for : \n" );
while( allExpires.hasMoreElements() ) {
Entry anExpire = (Entry) allExpires.nextElement();
fileList.append( " " + TimeUtils.toRelativeTimeMillis(anExpire.expiresAt) + " " + anExpire.file.getCanonicalPath() + "\n" );
}
LOG.info( fileList );
}
*/
if( removeunknowns )
removeUnknownFiles( dir );
}
void compressStreams( DataInputStream in ) throws IOException {
long start = TimeUtils.timeNow();
Hashtable reduced = new Hashtable(hash.size());
Vector shouldBeDeleted = new Vector(hash.size());
int i = 0;
try {
while (true) {
int action = in.readInt();
File file = new File(in.readUTF());
long expiresAt = in.readLong();
long cacheLifetime = in.readLong();
if (file.exists()) {
String filepath = file.getCanonicalPath();
switch (action) {
case SCHEDULE:
if ( expiresAt > start ) {
/*
if (LOG.isEnabledFor(Priority.DEBUG)) {
LOG.debug( "* " + TimeUtils.toRelativeTimeMillis(expiresAt) + " " + filepath );
}
*/
Entry entry = (Entry) reduced.get( filepath );
if( null == entry )
entry = new Entry( file, expiresAt, cacheLifetime );
else {
if( entry.expiresAt < expiresAt ) {
entry.expiresAt = expiresAt;
entry.cacheLifetime = cacheLifetime;
}
}
reduced.put( filepath, entry );
shouldBeDeleted.removeElement( filepath );
} else {
if( !shouldBeDeleted.contains( filepath ) )
shouldBeDeleted.addElement( filepath );
}
break;
case CANCEL:
reduced.remove( file.getCanonicalPath() );
cancelFileExpiration(file);
shouldBeDeleted.addElement( filepath );
break;
default :
if (LOG.isEnabledFor(Priority.INFO))
LOG.warn( "Unexpected Action in log read." );
}
} else {
if (LOG.isEnabledFor(Priority.DEBUG)) {
LOG.debug( "Forcing cancellation of deleted file : " + file.getPath() );
}
cancelFileExpiration(file);
}
i++;
}
} catch (EOFException e) {
// ugh, this is bad code, but should work all the time
if (LOG.isEnabledFor(Priority.INFO)) {
LOG.info( "Caught EOF Exception after processing " + i + " records from log" );
}
// now we have update the in memory table with the entries we found
// in the log.
Enumeration entries = reduced.elements();
while( entries.hasMoreElements() ) {
Entry anEntry = (Entry) entries.nextElement();
if( !scheduleFileExpiration( anEntry.file, TimeUtils.toRelativeTimeMillis( anEntry.expiresAt, start), anEntry.cacheLifetime ) ) {
// the expiration service refused to record this, so we will make sure it gets written.
/*
if (LOG.isEnabledFor(Priority.DEBUG)) {
LOG.debug( "x " + anEntry.expiresAt + " " + anEntry.file.getCanonicalPath() );
}
*/
logWrite( SCHEDULE, anEntry.file, anEntry.expiresAt, anEntry.cacheLifetime );
}
}
// now we have phyiscally delete the orphaned files
entries = shouldBeDeleted.elements();
while( entries.hasMoreElements() ) {
File file = new File( (String) entries.nextElement() );
try {
boolean needsDelete = true;
if (listener != null)
needsDelete = listener.expired(file);
if( needsDelete )
file.delete();
} catch (Throwable t) {
if (LOG.isEnabledFor(Priority.DEBUG))
LOG.debug("Throwable caught while dispatching expiration listener.", t);
}
}
}
}
/**
* Removes any file found in the specified directory which cannot be
* matched against an entry in the expiration table will be removed.
*
* @param aDir the directory to be cleaned.
**/
private void removeUnknownFiles( File aDir ) {
String[] list = aDir.list();
for (int i = 0; list != null && i < list.length; i++) {
try {
File f = new File( aDir, list[i]);
if( f.isDirectory() ) {
removeUnknownFiles( f );
continue;
}
if( f.getName().equals( SCHED_DB_FILENAME ) ) {
// if we are at the root of the tree, ignore our file
if( this.dir.equals( f.getParentFile() ) )
continue;
if (LOG.isEnabledFor(Priority.WARN))
LOG.warn("Found a scheduler DB (" + f.getCanonicalPath() +
") inside the dirs we are monitoring. bad mojo." );
continue;
}
if ( null == hash.get(f.getCanonicalPath()) ) {
/*
if (LOG.isEnabledFor(Priority.DEBUG))
LOG.debug( "- ???????? " + f.getCanonicalPath() );
*/
try {
boolean needsDelete = true;
if (listener != null)
needsDelete = listener.expired(f);
if( needsDelete )
f.delete();
} catch (Throwable t) {
if (LOG.isEnabledFor(Priority.DEBUG))
LOG.debug("Throwable caught while dispatching expiration listener.", t);
}
}
} catch ( Exception badFile ) {
if (LOG.isEnabledFor(Priority.DEBUG))
LOG.debug("problem working with file : " + list[i], badFile);
continue;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -