package com.eactive.eai.rms.onl.server.repository;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.apache.commons.collections.map.MultiKeyMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.common.ByteBuffer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

import com.eactive.eai.rms.common.context.MonitoringContext;

/**
 * The Class TransactionRepository.
 * <ul>
 * <li>1. Function :{@link com.eactive.eai.rms.onl.vo.TransactionTrackingVo} �� �����
 * �Դϴ�. </li>
 * <li>2. Summary :</li>
 * <li>3. Notification :</li>
 * </ul>
 * 
 * @author : $Author: ��â�� $
 * @version : $Revision: 1.11.6.2 $
 * @see com.eactive.eai.rms.onl.vo.TransactionTrackingVo
 * @see com.eactive.eai.rms.server.backup.TransactionRepositoryBackupJob
 * @see TransactionRepositoryService
 */
@Scope(value = "singleton")
@Repository("transactionRepository")
public class TransactionRepository implements Serializable {

    /** The Constant serialVersionUID. */
    private static final long serialVersionUID = -8968729820736492173L;

    /** The Constant logger. */
    private static final Log logger = LogFactory
            .getLog(TransactionRepository.class);

    /** The repository. */
    private MultiKeyMap repository;

    /** The monitoring context. */
    @Autowired
    @Qualifier("monitoringContext")
    private transient MonitoringContext monitoringContext;

    /**
     * Inits the repository.
     */
    @PostConstruct
    public void initRepository() {

        TransactionRepository transactionRepository = readTransactionRepository();
        repository = transactionRepository.getRepository();
        if (logger.isDebugEnabled()) {
            logger.debug("Transaction Repository : " + transactionRepository);
        }
    }

    /**
     * Destroy repository.
     */
    @PreDestroy
    public void destroyRepository() {
        writeTransactionRepository(this);
    }

    /**
     * Gets the repository.
     * 
     * @return the repository
     */
    public MultiKeyMap getRepository() {
        return repository;
    }
    
    public void clearRepository() {
    	repository.clear();
    }
    
    public void clearRepository( String hostName, String instance ) {
    	repository.remove(hostName, instance );
    }
    
    public void checkRepository() {
    	logger.debug("check transactionRepository size=" + repository.size() );
    }
    

    /**
     * Read transaction repository.
     * 
     * @return the transaction repository
     */
    public TransactionRepository readTransactionRepository() {
    	
    	if( true ) {
    		// 2010.01.22 Repository �� ���Ͽ� �������� �ʵ��� �����Ѵ�. ( YUN )
            TransactionRepository tmpRepo = new TransactionRepository();
            tmpRepo.repository = new MultiKeyMap();
    		return tmpRepo;
    	}

        RandomAccessFile aFile = null;
        FileChannel channel = null;
        ByteBuffer buffer = null;
        TransactionRepository transactionRepository = null;
        String key = null;
        File file = null;
        try {

            key = MonitoringContext.RMS_PREFIX
                    + MonitoringContext.TRANSACTION_REPOSITORY_PATH;

            file = new File(monitoringContext.getStringProperty(key,
                    "TransactionRepository"));

            aFile = new RandomAccessFile(file, "r");
            channel = aFile.getChannel();
            buffer = ByteBuffer.allocate((int) aFile.length());

            buffer.setAutoExpand(true);

            channel.read(buffer.buf());
            buffer.flip();

            transactionRepository = (TransactionRepository) buffer.getObject();

        } catch (Exception e) {

            logger.warn("Transaction Repository�� �д��� ������ �߻� �Ͽ����ϴ�. (" + key
                    + ":" + file + ")" + "�⺻ Repository�� ���� �մϴ�. ", e);

        } finally {
            if (aFile != null) {
                try {
                    aFile.close();
                } catch (IOException e) {
                    //e.printStackTrace();
                	logger.error("close error",e);
                }
            }

            if (buffer != null) {
                buffer.release();
            }
        }

        if (transactionRepository == null) {
            transactionRepository = new TransactionRepository();
            transactionRepository.repository = new MultiKeyMap();

            writeTransactionRepository(transactionRepository);
        }

        return transactionRepository;
    }

    /**
     * Write transaction repository.
     * 
     * @param transactionRepository
     *            the transaction repository
     */
    public synchronized void writeTransactionRepository(
            TransactionRepository transactionRepository) {
    	
    	if( true ) {
    		// 2010.01.22 Repository �� ���Ͽ��� ���� �ʵ��� �����Ѵ�. ( YUN )
    		return ;
    	}
    	
        RandomAccessFile aFile = null;
        FileChannel channel = null;
        ByteBuffer buffer = null;
        FileLock lock = null;
        String key = null;
        File file = null;
        try {

            key = MonitoringContext.RMS_PREFIX
                    + MonitoringContext.TRANSACTION_REPOSITORY_PATH;

            file = new File(monitoringContext.getStringProperty(key,
                    "TransactionRepository"));

            aFile = new RandomAccessFile(file, "rw");
            channel = aFile.getChannel();
            buffer = ByteBuffer.allocate(64);
            buffer.setAutoExpand(true);

            buffer.putObject(transactionRepository);
            buffer.flip();

            lock = channel.lock();
            aFile.setLength(0);
            channel.write(buffer.buf());

        } catch (Exception e) {
            logger.warn("TransactionRepository�� ���� �ϴ� ���� ������ �߻� �Ͽ����ϴ�. (" + key
                    + ":" + file + ")", e);
        } finally {
            if (lock != null) {
                try {
                    lock.release();
                } catch (Exception e) {
                	logger.error("Write transaction repository lock error",e);
                }
            }
            if (aFile != null) {
                try {
                    aFile.close();
                } catch (IOException e) {
                    //e.printStackTrace();
                	logger.error("close error",e);
                }
            }
            if (buffer != null) {
                buffer.release();
            }
        }
    }

}
