package org.maachang.comet.httpd.engine.comet ;

import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 各コメット内の要素を監視.
 *
 * @version 2007/08/24
 * @author  masahito suzuki
 * @since   MaachangComet 1.00
 */
class TimeoutCometMonitor extends Thread {
    
    /**
     * LOG.
     */
    private static final Log LOG = LogFactory.getLog( TimeoutCometMonitor.class ) ;
    
    /**
     * 巡回時間.
     * 30秒.
     */
    private static final long TIME = 30000L ;
    
    /**
     * 管理オブジェクト.
     */
    private Map<String,Comet> manager = null ;
    
    /**
     * 前回実行時間.
     */
    private long beforeTime = System.currentTimeMillis() ;
    
    /**
     * 停止フラグ.
     */
    private volatile boolean stopFlag = false ;
    
    /**
     * 停止フラグ用同期.
     */
    private Object stopSync = new Object() ;
    
    /**
     * コンストラクタ.
     * @param manager 対象のマネージャオブジェクトを設定します.
     */
    public TimeoutCometMonitor( Map<String,Comet> manager ) {
        this.manager = manager ;
        this.setDaemon( true ) ;
        this.start() ;
    }
    
    /**
     * デストラクタ.
     */
    protected void finalize() throws Exception {
        this.clear() ;
    }
    
    /**
     * クリア.
     */
    public void clear() {
        stopThread() ;
    }
    
    /**
     * 実行状態を取得.
     * <BR><BR>
     * @return boolean 実行状態が返されます.
     */
    public boolean isStopThread() {
        boolean ret = false ;
        synchronized( stopSync ) {
            ret = stopFlag ;
        }
        return ret ;
    }
    
    /**
     * スレッドアイドル.
     */
    private static final long IDLE_TIME = 500L ;
    
    /**
     * スレッド処理.
     */
    public void run() {
        try {
            for( ;; ) {
                if( isStopThread() == true ) {
                    break ;
                }
                try { Thread.sleep( IDLE_TIME ) ; } catch( Exception e ) {}
                try {
                    if( beforeTime + TIME <= System.currentTimeMillis() ) {
                        try {
                            if( manager == null ) {
                                continue ;
                            }
                            if( manager.size() > 0 ) {
                                Object[] objs = manager.keySet().toArray() ;
                                int len = objs.length ;
                                for( int i = 0 ; i < len ; i ++ ) {
                                    if( isStopThread() == true ) {
                                        break ;
                                    }
                                    try { Thread.sleep( 30L ) ; } catch( Exception e ) {}
                                    Comet comet = manager.get( ( String )objs[ i ] ) ;
                                    if( comet == null ) {
                                        manager.remove( ( String )objs[ i ] ) ;
                                        continue ;
                                    }
                                    objs[ i ] = null ;
                                    comet.cleanConnection() ;
                                }
                            }
                        } finally {
                            beforeTime = System.currentTimeMillis() ;
                        }
                    }
                    
                } catch( OutOfMemoryError mm ) {
                    LOG.error( "OutOfMemoryError",mm ) ;
                } catch( Exception e ) {
                    LOG.error( "error",e ) ;
                } finally {
                }
            }
        } finally {
            LOG.warn( "## stopThread:" + this.getClass().getName() ) ;
        }
    }
    
    private void stopThread() {
        synchronized( stopSync ) {
            stopFlag = true ;
        }
    }
}
