// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.cluster;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.ejb.Local;
import javax.naming.ConfigurationException;

import junit.framework.TestCase;

import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;

import com.cloud.agent.Listener;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.cluster.dao.StackMaidDao;
import com.cloud.cluster.dao.StackMaidDaoImpl;
import com.cloud.configuration.Config;
import com.cloud.configuration.DefaultInterceptorLibrary;
import com.cloud.configuration.dao.ConfigurationDaoImpl;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.host.Status.Event;
import com.cloud.serializer.SerializerHelper;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.MockComponentLocator;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;

public class CheckPointManagerTest extends TestCase {
    private final static Logger s_logger = Logger.getLogger(CheckPointManagerTest.class);
    
    @Override
    @Before
    public void setUp() {
        MockComponentLocator locator = new MockComponentLocator("management-server");
        locator.addDao("StackMaidDao", StackMaidDaoImpl.class);
        locator.addDao("ConfigurationDao", ConfigurationDaoImpl.class);
        locator.addManager("ClusterManager", MockClusterManager.class);
        locator.makeActive(new DefaultInterceptorLibrary());
        MockMaid.map.clear();
        s_logger.info("Cleaning up the database");
        Connection conn = Transaction.getStandaloneConnection();
        try {
            conn.setAutoCommit(true);
            PreparedStatement stmt = conn.prepareStatement("DELETE FROM stack_maid");
            stmt.executeUpdate();
            stmt.close();
            conn.close();
        } catch (SQLException e) {
            throw new CloudRuntimeException("Unable to setup database", e);
        }
    }
    
    @Override
    @After
    public void tearDown() throws Exception {
    }
    
    public void testCompleteCase() throws Exception {
        ComponentLocator locator = ComponentLocator.getCurrentLocator();
        
        CheckPointManagerImpl taskMgr = ComponentLocator.inject(CheckPointManagerImpl.class);
        assertTrue(taskMgr.configure("TaskManager", new HashMap<String, Object>()));
        assertTrue(taskMgr.start());
        
        MockMaid delegate = new MockMaid();
        delegate.setValue("first");
        long taskId = taskMgr.pushCheckPoint(delegate);
        
        StackMaidDao maidDao = locator.getDao(StackMaidDao.class);
        CheckPointVO task = maidDao.findById(taskId);
        
        assertEquals(task.getDelegate(), MockMaid.class.getName());
        MockMaid retrieved = (MockMaid)SerializerHelper.fromSerializedString(task.getContext()); 
        assertEquals(retrieved.getValue(), delegate.getValue());
        
        delegate.setValue("second");
        taskMgr.updateCheckPointState(taskId, delegate);

        task = maidDao.findById(taskId);
        assertEquals(task.getDelegate(), MockMaid.class.getName());
        retrieved = (MockMaid)SerializerHelper.fromSerializedString(task.getContext()); 
        assertEquals(retrieved.getValue(), delegate.getValue());
        
        taskMgr.popCheckPoint(taskId);
        assertNull(maidDao.findById(taskId));
    }
    
    public void testSimulatedReboot() throws Exception {
        ComponentLocator locator = ComponentLocator.getCurrentLocator();
        
        CheckPointManagerImpl taskMgr = ComponentLocator.inject(CheckPointManagerImpl.class);
        assertTrue(taskMgr.configure("TaskManager", new HashMap<String, Object>()));
        assertTrue(taskMgr.start());
        
        MockMaid maid = new MockMaid();
        maid.setValue("first");
        long taskId = taskMgr.pushCheckPoint(maid);
        
        StackMaidDao maidDao = locator.getDao(StackMaidDao.class);
        CheckPointVO task = maidDao.findById(taskId);
        
        assertEquals(task.getDelegate(), MockMaid.class.getName());
        MockMaid retrieved = (MockMaid)SerializerHelper.fromSerializedString(task.getContext()); 
        assertEquals(retrieved.getValue(), maid.getValue());

        taskMgr.stop();
        
        assertNotNull(MockMaid.map.get(maid.getSeq()));
        
        taskMgr = ComponentLocator.inject(CheckPointManagerImpl.class);
        HashMap<String, Object> params = new HashMap<String, Object>();
        params.put(Config.TaskCleanupRetryInterval.key(), "1");
        taskMgr.configure("TaskManager", params);
        taskMgr.start();
        
        int i = 0;
        while (MockMaid.map.get(maid.getSeq()) != null && i++ < 5) {
            Thread.sleep(1000);
        }
        
        assertNull(MockMaid.map.get(maid.getSeq()));
    }
    
    public void testTakeover() throws Exception {
        ComponentLocator locator = ComponentLocator.getCurrentLocator();
        
        CheckPointManagerImpl taskMgr = ComponentLocator.inject(CheckPointManagerImpl.class);
        assertTrue(taskMgr.configure("TaskManager", new HashMap<String, Object>()));
        assertTrue(taskMgr.start());
        
        MockMaid delegate = new MockMaid();
        delegate.setValue("first");
        long taskId = taskMgr.pushCheckPoint(delegate);
        
        StackMaidDao maidDao = locator.getDao(StackMaidDao.class);
        CheckPointVO task = maidDao.findById(taskId);
        
        assertEquals(task.getDelegate(), MockMaid.class.getName());
        MockMaid retrieved = (MockMaid)SerializerHelper.fromSerializedString(task.getContext()); 
        assertEquals(retrieved.getValue(), delegate.getValue());

        Connection conn = Transaction.getStandaloneConnection();
        try {
            conn.setAutoCommit(true);
            PreparedStatement stmt = conn.prepareStatement("update stack_maid set msid=? where msid=?");
            stmt.setLong(1, 1234);
            stmt.setLong(2, ManagementServerNode.getManagementServerId());
            stmt.executeUpdate();
            stmt.close();
        } finally {
            conn.close();
        }
        
        MockClusterManager clusterMgr = (MockClusterManager)locator.getManager(ClusterManager.class);
        clusterMgr.triggerTakeover(1234);
        
        int i = 0;
        while (MockMaid.map.get(delegate.getSeq()) != null && i++ < 500) {
            Thread.sleep(1000);
        }
        
        assertNull(MockMaid.map.get(delegate.getSeq()));
    }
    
    public static class MockMaid implements CleanupMaid {
        private static int s_seq = 1;
        public static Map<Integer, MockMaid> map = new ConcurrentHashMap<Integer, MockMaid>();
        
        int seq;
        boolean canBeCleanup;
        String value;
        
        protected MockMaid() {
            canBeCleanup = true;
            seq = s_seq++;
            map.put(seq, this);
        }
        
        public int getSeq() {
            return seq;
        }
        
        public String getValue() {
            return value;
        }
        
        public void setCanBeCleanup(boolean canBeCleanup) {
            this.canBeCleanup = canBeCleanup;
        }

        @Override
        public int cleanup(CheckPointManager checkPointMgr) {
            s_logger.debug("Cleanup called for " + seq);
            map.remove(seq);
            return canBeCleanup ? 0 : -1;
        }
        
        public void setValue(String value) {
            this.value = value;
        }
        
        @Override
        public String getCleanupProcedure() {
            return "No cleanup necessary";
        }
    }
    
    @Local(value=ClusterManager.class)
    public static class MockClusterManager implements ClusterManager {
        String _name;
        ClusterManagerListener _listener;

        @Override
        public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
            _name = name;
            return true;
        }

        @Override
        public boolean start() {
            return true;
        }

        @Override
        public boolean stop() {
            return true;
        }

        @Override
        public String getName() {
            return _name;
        }

        @Override
        public void OnReceiveClusterServicePdu(ClusterServicePdu pdu) {
            throw new CloudRuntimeException("Not implemented");
        }
        
        @Override
        public Answer[] execute(String strPeer, long agentId, Command[] cmds, boolean stopOnError) {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public Answer[] sendToAgent(Long hostId, Command[] cmds, boolean stopOnError) throws AgentUnavailableException, OperationTimedoutException {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public boolean executeAgentUserRequest(long agentId, Event event) throws AgentUnavailableException {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public Boolean propagateAgentEvent(long agentId, Event event) throws AgentUnavailableException {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public int getHeartbeatThreshold() {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public long getManagementNodeId() {
            return ManagementServerNode.getManagementServerId();
        }

        @Override
        public boolean isManagementNodeAlive(long msid) {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public boolean pingManagementNode(long msid) {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public long getCurrentRunId() {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public String getSelfPeerName() {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public String getSelfNodeIP() {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public String getPeerName(long agentHostId) {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public void registerListener(ClusterManagerListener listener) {
            _listener = listener;
        }

        @Override
        public void unregisterListener(ClusterManagerListener listener) {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public ManagementServerHostVO getPeer(String peerName) {
            throw new UnsupportedOperationException("Not implemented");
        }

        @Override
        public void broadcast(long agentId, Command[] cmds) {
            throw new UnsupportedOperationException("Not implemented");
        }
        
        public void triggerTakeover(long msId) {
            ManagementServerHostVO node = new ManagementServerHostVO();
            node.setMsid(msId);
            
            List<ManagementServerHostVO> lst = new ArrayList<ManagementServerHostVO>();
            lst.add(node);
            
            _listener.onManagementNodeLeft(lst, ManagementServerNode.getManagementServerId());
        }
        
        protected MockClusterManager() {
        }
        
        @Override
        public boolean rebalanceAgent(long agentId, Event event, long currentOwnerId, long futureOwnerId) throws AgentUnavailableException, OperationTimedoutException {
            return false;
        }
        
        @Override
        public boolean isAgentRebalanceEnabled() {
            return false;
        }

		@Override
        public Boolean propagateResourceEvent(long agentId, com.cloud.resource.ResourceState.Event event) throws AgentUnavailableException {
	        // TODO Auto-generated method stub
	        return null;
        }

		@Override
        public boolean executeResourceUserRequest(long hostId, com.cloud.resource.ResourceState.Event event) throws AgentUnavailableException {
	        // TODO Auto-generated method stub
	        return false;
        }

        /* (non-Javadoc)
         * @see com.cloud.cluster.ClusterManager#executeAsync(java.lang.String, long, com.cloud.agent.api.Command[], boolean)
         */
        @Override
        public void executeAsync(String strPeer, long agentId, Command[] cmds, boolean stopOnError) {
            // TODO Auto-generated method stub
            
        }
    }
    
}
