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

import java.util.Iterator;
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 CometMonitor extends Thread {
    
    /**
     * LOG.
     */
    private static final Log LOG = LogFactory.getLog( CometMonitor.class ) ;
    
    /**
     * 巡回時間.
     * 5秒.
     */
    private static final long TIME = 5000L ;
    
    /**
     * 管理オブジェクト.
     */
    private Map<String,Comet> manager = null ;
    
    /**
     * 前回実行時間.
     */
    private long beforeTime = System.currentTimeMillis() ;
    
    /**
     * 停止フラグ.
     */
    private volatile boolean stopFlag = false ;
    
    /**
     * 停止フラグ用同期.
     */
    private Object stopSync = new Object() ;
    
    /**
     * コンストラクタ.
     * @param manager 対象のマネージャオブジェクトを設定します.
     */
    public CometMonitor( 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 = 1000L ;
    
    /**
     * スレッド処理.
     */
    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 ) {
                                Iterator it = manager.keySet().iterator() ;
                                while( it.hasNext() ) {
                                    try {
                                        String key = ( String )it.next() ;
                                        if( isStopThread() == true ) {
                                            break ;
                                        }
                                        Comet comet = manager.get( key ) ;
                                        if( comet == null ) {
                                            manager.remove( key ) ;
                                            continue ;
                                        }
                                        comet.cleanConnection() ;
                                        Thread.sleep( 5L ) ;
                                    } catch( InterruptedException iee ) {
                                        throw iee ;
                                    } catch( Exception ee ) {
                                        LOG.error( "error",ee ) ;
                                    }
                                }
                            }
                        } finally {
                            beforeTime = System.currentTimeMillis() ;
                        }
                    }
                    
                } catch( InterruptedException ie ) {
                    break ;
                } 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 ;
        }
    }
}
