⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileexpirationservice.java

📁 jxme的一些相关程序,主要是手机上程序开发以及手机和计算机通信的一些程序资料,程序编译需要Ant支持
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 2001 Sun Microsystems, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in
 * the documentation and/or other materials provided with the
 * distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 * if any, must include the following acknowledgment:
 * "This product includes software developed by the
 * Sun Microsystems, Inc. for Project JXTA."
 * Alternately, this acknowledgment may appear in the software itself,
 * if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA"
 * must not be used to endorse or promote products derived from this
 * software without prior written permission. For written
 * permission, please contact Project JXTA at http://www.jxta.org.
 *
 * 5. Products derived from this software may not be called "JXTA",
 * nor may "JXTA" appear in their name, without prior written
 * permission of Sun.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of Project JXTA. For more
 * information on Project JXTA, please see
 * <http://www.jxta.org/>.
 *
 * This license is based on the BSD license adopted by the Apache Foundation.
 *
 * $Id: FileExpirationService.java,v 1.22 2002/05/16 05:55:46 bondolo Exp $
 */
package net.jxta.impl.cm;

import java.io.*;
import java.util.*;

import java.lang.IllegalArgumentException;

import org.apache.log4j.Category;
import org.apache.log4j.Priority;

import net.jxta.impl.util.TimeUtils;

class FileExpirationService {
    
    static final Category LOG = Category.getInstance(FileExpirationService.class.getName());
    
    static final String SCHED_DB_FILENAME = "scheduler.db";
    static final String TEMP_SCHED_DB_FILENAME = ".tmp.scheduler.db";
    
    static final int  SCHEDULE          = 1;
    static final int  CANCEL            = 2;
    
    static final long COMPRESS_INTERVAL = 30 * TimeUtils.AMINUTE;
    static final int  MOD_THRESHOLD     = 128;
    
    File             dir;
    File             db;
    File             tmpDb;
    
    DataOutputStream out;
    FileDescriptor   outFD;
    Hashtable        hash;
    int              mods;
    
    SchedulerService ss;
    SchedulerService.PendingAction pendingCompressAction;
    ExpirationListener listener;
    
    /**
     *  Interface called when the time finally comes for the file to be deleted.
     *  The expiration service does not actually delete the files, because they
     *  may be republished during the call of the 'expire' handler.
     **/
    interface ExpirationListener {
        
        /**
         *  The file which has expired and needs to be deleted. In some rare
         *  cases the file provided may no longer exist (It's not the expiration
         *  service's fault) these notifications are provided so that the
         *  listener can take recovery action.
         *
         *  @param file the file which has expired.
         *  @return true if the expiration service should delete the file
         *  otherwise false.
         *
         **/
        public boolean expired(File file);
    }
    
    /**
     *  inner class for performing periodic compression of the expiration log
     *  file.
     **/
    class CleanupAction implements SchedulerService.Action {
        
        public void perform(SchedulerService ss) {
            
            try{
                synchronized( FileExpirationService.this ) {
                    if (db.exists())
                        compress(true);
                    else {
                        if (LOG.isEnabledFor(Priority.WARN))
                            LOG.warn("Expiry log not present!" );
                    }
                }
            } catch (IOException e) {
                if (LOG.isEnabledFor(Priority.DEBUG))
                    LOG.debug("Compression of log stream failed.", e);
            }
            
            // still re-schedule, because the administrator may
            // see the log messages and do something that will
            // make the compress action succeed later.  or something.
            pendingCompressAction =
            ss.scheduleAction(this, COMPRESS_INTERVAL);
        }
    }
    
    /**
     *  Testing action for advancing the clock so that things magically expire
     *  more quickly than they would normally.
     **/
    static class TimewarpAction implements SchedulerService.Action {
        
        private long warpby;
        
        private long warpinterval;
        
        public TimewarpAction( long warpinterval, long warpby  ) {
            this.warpinterval = warpinterval;
            this.warpby = warpby;
        }
        
        public void perform(SchedulerService ss) {
            
            ss.scheduleAction(this, warpinterval + warpby );
            
            synchronized (ss) {
                TimeUtils.timeWarp( warpby );
                
                ss.notifyAll();
            }
        }
    }
    
    /**
     *  inner class which is called by the Scheduler service when an entry
     *  expires.
     **/
    class ExpireAction implements SchedulerService.Action {
        Entry entry;
        
        ExpireAction(Entry entry) {
            this.entry = entry;
        }
        
        public void perform(SchedulerService ss) throws IOException {
            
            // Do not synchronize for the listener, it never changes after
            // construction.
            // But do synchronize for hash.remove. Other methods rely
            // on the hashtable not changing while they're synchronized.
            
            try {
                boolean needsDelete = true;
                
                if (listener != null)
                    needsDelete = listener.expired(entry.file);
                
                if( needsDelete )
                    entry.file.delete();
            } catch ( Throwable t ) {
                if (LOG.isEnabledFor(Priority.DEBUG))
                    LOG.debug( "Throwable caught while dispatching expiration listener.", t );
            } finally {
                // remove this entry from the hash, its going away.
                synchronized(FileExpirationService.this) {
                    hash.remove(entry.file.getCanonicalPath());
                }
                
                // mark this entry as dead.
                synchronized( entry ) {
                    entry.file = null; // dead entry.
                    entry.expiryAction = null;
                }
            }
        }
    }
    
    /**
     *  static inner class for entries in the expiration hash table.
     **/
    static class Entry {
        
        /**
         *  The file
         **/
        File file;
        
        /**
         *  The absolute time in milliseconds at which this document will expire.
         **/
        long expiresAt;
        
        /**
         *  the duration of validity in milliseconds within a cache other than
         *  its original publication location.
         **/
        long cacheLifetime;
        
        /**
         *  The action to be performed when it expires.
         **/
        SchedulerService.PendingAction expiryAction;
        
        /**
         * @param  expiresAt time after which the document is removed from
         * the local cahce. Expressed in absolute milliseconds.
         * @param  cacheLifetime  time after which the document is removed from
         * remote caches. Expressed in relative milliseconds.
         */
        Entry( File file, long expiresAt, long cacheLifetime ) {
            this.file                = file;
            this.expiresAt           = expiresAt;
            this.cacheLifetime       = cacheLifetime;
        }
    }
    
    /**
     *  @param  ss  The scheduler used to be used.
     *  @param  dir  The directory containing the files being managed.
     *  @param  listener who will be told when files expires.
     */
    FileExpirationService( SchedulerService ss,
    File dir,
    ExpirationListener listener) throws IOException {
        this.ss       = ss;
        this.dir      = dir;
        this.listener = listener;
        
        hash = new Hashtable();
        
        if ( !dir.exists() )
            if( !dir.mkdirs() ) {
                throw new IOException( "Could not create target directory" );
            }
            else if( !dir.isDirectory() ) {
                throw new IllegalArgumentException( "dir exists and is not a directory" );
            }
        
        db    = new File( dir, SCHED_DB_FILENAME );
        mods  = 0;
        
        tmpDb = new File( dir, TEMP_SCHED_DB_FILENAME );
        
        if ( tmpDb.exists() )
            tmpDb.delete();
        
        if ( tmpDb.exists() ) {
            if (LOG.isEnabledFor(Priority.WARN))
                LOG.warn("Could not delete temp file. This will be a problem..." );
        }
        
        // if there is an existing db, we populate the hash table from it.
        try {
            if (db.exists()) {
                compress( true );
            } else {
                openlog( db, false );
            }
        } catch ( IOException problems ) {
            if (LOG.isEnabledFor(Priority.ERROR))
                LOG.error("Could not open existing db or make a new one.", problems );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -