/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with 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.
 */

package org.apache.oozie.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.hadoop.util.Shell;
import org.apache.oozie.CoordinatorActionBean;
import org.apache.oozie.client.CoordinatorAction.Status;
import org.apache.oozie.client.rest.JsonBean;
import org.apache.oozie.dependency.hcat.HCatMessageHandler;
import org.apache.oozie.executor.jpa.BatchQueryExecutor;
import org.apache.oozie.executor.jpa.CoordActionsDeleteJPAExecutor;
import org.apache.oozie.test.ZKXTestCase;
import org.apache.oozie.util.HCatURI;
import org.apache.oozie.service.RecoveryService.RecoveryRunnable;

public class TestHAPartitionDependencyManagerService extends ZKXTestCase {

    protected Services services;
    protected String server;
    protected String db;
    protected String table1;
    protected String table2;
    protected String part1;
    protected String part2;
    protected String part3;

    protected void setUp() throws Exception {
        super.setUp();
        services = super.setupServicesForHCatalog(Services.get());
        super.setupHCatalogServer();
        // disable recovery service
        services.getConf().setInt(RecoveryService.CONF_SERVICE_INTERVAL, 1000000);
        // disable regular cache purge
        services.getConf().setInt(PartitionDependencyManagerService.CACHE_PURGE_INTERVAL, 1000000);
        server = super.getHCatalogServer().getMetastoreAuthority();
        services.init();
    }

    protected void tearDown() throws Exception {
        services.destroy();
        super.tearDown();
    }

    private void populateTable() throws Exception {
        dropTable(db, table1, true);
        dropTable(db, table2, true);
        dropDatabase(db, true);
        createDatabase(db);
        createTable(db, table1, "dt,country");
        createTable(db, table2, "dt,country");
    }

    protected String getSanitizedTestCaseDir() {
        // On Windows, the working directory will have a colon from to the drive letter. Because colons
        // are not allowed in DFS paths, we remove it. Also, prepend a backslash to simulate an absolute path.
        if(Shell.WINDOWS) {
            return "\\" + getTestCaseDir().replaceAll(":", "");
        }
        else {
            return getTestCaseDir();
        }
    }

    public void testDependencyCacheWithHA() throws Exception {

        db = "default";
        table1 = "mytbl";
        table2 = "mytb2";
        part1 = "dt=20120101;country=us";
        part2 = "dt=20120102;country=us";
        part3 = "dt=20120103;country=us";
        String newHCatDependency1 = "hcat://" + server + "/" + db + "/" + table1 + "/" + part1;
        String newHCatDependency2 = "hcat://" + server + "/" + db + "/" + table1 + "/" + part2;
        String newHCatDependency3 = "hcat://" + server + "/" + db + "/" + table2 + "/" + part3;
        HCatURI dep1 = new HCatURI(newHCatDependency1);
        HCatURI dep2 = new HCatURI(newHCatDependency2);
        HCatURI dep3 = new HCatURI(newHCatDependency3);
        // create db, table and partitions
        populateTable();

        String actionId1 = addInitRecords(newHCatDependency1);
        String actionId2 = addInitRecords(newHCatDependency2);
        String actionId3 = addInitRecords(newHCatDependency3);

        // Assume dependency cache on dummy server with missing push dependencies registered
        PartitionDependencyManagerService dummyPdms = new PartitionDependencyManagerService();
        PartitionDependencyManagerService pdms = Services.get().get(PartitionDependencyManagerService.class);
        dummyPdms.init(Services.get());
        dummyPdms.addMissingDependency(dep1, actionId1);
        dummyPdms.addMissingDependency(dep2, actionId2);
        dummyPdms.addMissingDependency(dep3, actionId3);

        Collection<String> waitingActions = (Collection<String>)dummyPdms.getWaitingActions(dep1);
        assertEquals(1, waitingActions.size());
        waitingActions = (Collection<String>)dummyPdms.getWaitingActions(dep2);
        assertEquals(1, waitingActions.size());
        waitingActions = (Collection<String>)dummyPdms.getWaitingActions(dep3);
        assertEquals(1, waitingActions.size());

        //Dependency cache on living server doesn't have these partitions registered at this point
        waitingActions = (Collection<String>)pdms.getWaitingActions(dep1);
        assertNull(waitingActions);
        waitingActions = (Collection<String>)pdms.getWaitingActions(dep2);
        assertNull(waitingActions);
        waitingActions = (Collection<String>)pdms.getWaitingActions(dep3);
        assertNull(waitingActions);

        //Assume dummy server is down, and recovery service on living server pick up these jobs
        dummyPdms.destroy();
        Runnable recoveryRunnable = new RecoveryRunnable(60, 0, 60);
        recoveryRunnable.run();
        waitFor(30 * 1000, new Predicate() {
            public boolean evaluate() throws Exception {
                Collection<String> waitingActions;
                PartitionDependencyManagerService pdms = Services.get().get(PartitionDependencyManagerService.class);
                HCatURI dep1 = new HCatURI("hcat://"+ server + "/" + db + "/" + table1 + "/" + part1);
                HCatURI dep2 = new HCatURI("hcat://"+ server + "/" + db + "/" + table1 + "/" + part2);
                HCatURI dep3 = new HCatURI("hcat://"+ server + "/" + db + "/" + table2 + "/" + part3);
                waitingActions = pdms.getWaitingActions(dep1);
                if(waitingActions == null) {
                    return false;
                }
                waitingActions = pdms.getWaitingActions(dep2);
                if(waitingActions == null) {
                    return false;
                }
                waitingActions = pdms.getWaitingActions(dep3);
                if(waitingActions == null) {
                    return false;
                }
                return true;
            }
        });
        //Dependency cache on living server has missing partitions added
        waitingActions = (Collection<String>)pdms.getWaitingActions(dep1);
        assertEquals(1, waitingActions.size());
        assertTrue(waitingActions.contains(actionId1));
        waitingActions = (Collection<String>)pdms.getWaitingActions(dep2);
        assertEquals(1, waitingActions.size());
        assertTrue(waitingActions.contains(actionId2));
        waitingActions = (Collection<String>)pdms.getWaitingActions(dep3);
        assertEquals(1, waitingActions.size());
        assertTrue(waitingActions.contains(actionId3));

        HCatAccessorService hcatService = Services.get().get(HCatAccessorService.class);
        // mytbl and mytb2 registered to topic map to receive notification
        assertTrue(hcatService.isRegisteredForNotification(dep1));
        assertTrue(hcatService.isRegisteredForNotification(dep2));
        assertTrue(hcatService.isRegisteredForNotification(dep3));
    }

    protected void addMissingDependencyAndRegister(HCatURI hcatURI, String actionId, PartitionDependencyManagerService pdms) {
        pdms.addMissingDependency(hcatURI, actionId);
        HCatAccessorService hcatService = Services.get().get(HCatAccessorService.class);
        if (!hcatService.isRegisteredForNotification(hcatURI)) {
            hcatService.registerForNotification(hcatURI, hcatURI.getDb() + "." + hcatURI.getTable(),
                    new HCatMessageHandler(hcatURI.getServer()));
        }
    }

    public void testPurgeMissingDependencies() throws Exception{
        services.setService(ZKJobsConcurrencyService.class);
        PartitionDependencyManagerService pdms = services.get(PartitionDependencyManagerService.class);
        pdms.init(services);
        testPurgeMissingDependenciesForCache(pdms);
    }

    protected void testPurgeMissingDependenciesForCache(PartitionDependencyManagerService pdms) throws Exception{

        String actionId1 = "1234465451";
        String actionId2 = "1234465452";
        String actionId3 = "1234465453";

        // add partitions as missing
        HCatURI dep1 = new HCatURI("hcat://hcat-server1.domain.com:5080/mydb/mytbl1/dt=20120101;country=us");
        HCatURI dep2 = new HCatURI("hcat://hcat-server1.domain.com:5080/mydb/mytbl1/country=us;dt=20120101");
        HCatURI dep3 = new HCatURI("hcat://hcat-server2.domain.com:5080/mydb/mytbl2/dt=20120102;country=us");

        // actionId1-->(dep1,2), actionId2-->(dep2), actionId3-->(dep2,3)
        addMissingDependencyAndRegister(dep1, actionId1, pdms);
        addMissingDependencyAndRegister(dep2, actionId1, pdms);
        addMissingDependencyAndRegister(dep2, actionId2, pdms);
        addMissingDependencyAndRegister(dep2, actionId3, pdms);
        addMissingDependencyAndRegister(dep3, actionId3, pdms);

        List<String> waitingDep1 = (ArrayList<String>) pdms.getWaitingActions(dep1);
        assertEquals(waitingDep1.size(), 1);
        assertEquals(waitingDep1.get(0), actionId1);

        List<String> waitingDep2 = (ArrayList<String>) pdms.getWaitingActions(dep2);
        assertEquals(waitingDep2.size(), 3);
        for (String id : waitingDep2) {
            assertTrue(id.equals(actionId1) || id.equals(actionId2) || id.equals(actionId3));
        }
        List<String> waitingDep3 = (ArrayList<String>) pdms.getWaitingActions(dep3);
        assertEquals(waitingDep3.size(), 1);
        assertTrue(waitingDep3.get(0).equals(actionId3));

        // make only coordAction 1 to WAITING, the rest to RUNNING (only WAITING
        // remain dependency cache)
        ArrayList<JsonBean> insertList = new ArrayList<JsonBean>();
        CoordinatorActionBean coordAction1 = new CoordinatorActionBean();
        coordAction1.setId(actionId1);
        coordAction1.setStatus(Status.WAITING);
        insertList.add(coordAction1);
        CoordinatorActionBean coordAction2 = new CoordinatorActionBean();
        coordAction2.setId(actionId2);
        coordAction2.setStatus(Status.RUNNING);
        insertList.add(coordAction2);
        CoordinatorActionBean coordAction3 = new CoordinatorActionBean();
        coordAction3.setId(actionId3);
        coordAction3.setStatus(Status.RUNNING);
        insertList.add(coordAction3);
        BatchQueryExecutor.getInstance().executeBatchInsertUpdateDelete(insertList, null, null);

        // run cache purge
        Services.get().getConf().setInt(PartitionDependencyManagerService.CACHE_PURGE_TTL, 0);
        pdms.runCachePurgeWorker();

        // only coord Action 1 still in dependency cache
        waitingDep1 = (ArrayList<String>) pdms.getWaitingActions(dep1);
        assertEquals(waitingDep1.size(), 1);
        assertTrue(waitingDep1.get(0).equals(actionId1));

        // only coord Action 1 still in dependency cache
        waitingDep2 = (ArrayList<String>) pdms.getWaitingActions(dep2);
        assertEquals(waitingDep2.size(), 1);
        assertTrue(waitingDep2.get(0).equals(actionId1));

        waitingDep3 = (ArrayList<String>) pdms.getWaitingActions(dep3);
        assertNull(waitingDep3);

        HCatAccessorService hcatService = Services.get().get(HCatAccessorService.class);
        // mytbl1 should be still in topic map
        assertTrue(hcatService.isRegisteredForNotification(dep1));
        // mytbl1 should be still in topic map
        assertTrue(hcatService.isRegisteredForNotification(dep2));
        // mytbl2 should NOT be in topic map
        assertFalse(hcatService.isRegisteredForNotification(dep3));
    }

    public void testCheckAfterActionDelete() throws Exception {
        Services.get().setService(ZKJobsConcurrencyService.class);
        Services.get().get(ConfigurationService.class).getConf()
                .setInt(PartitionDependencyManagerService.CACHE_PURGE_TTL, 0);

        db = "default";
        table1 = "mytbl";
        table2 = "mytb2";
        part1 = "dt=20120101;country=us";
        part2 = "dt=20120102;country=us";
        part3 = "dt=20120103;country=us";
        String newHCatDependency1 = "hcat://" + server + "/" + db + "/" + table1 + "/" + part1;
        String newHCatDependency2 = "hcat://" + server + "/" + db + "/" + table1 + "/" + part2;
        String newHCatDependency3 = "hcat://" + server + "/" + db + "/" + table2 + "/" + part3;
        HCatURI dep1 = new HCatURI(newHCatDependency1);
        HCatURI dep2 = new HCatURI(newHCatDependency2);
        HCatURI dep3 = new HCatURI(newHCatDependency3);
        // create db, table and partitions
        populateTable();

        String actionId1 = addInitRecords(newHCatDependency1);
        String actionId2 = addInitRecords(newHCatDependency2);
        String actionId3 = addInitRecords(newHCatDependency3);

        PartitionDependencyManagerService pdms = Services.get().get(PartitionDependencyManagerService.class);
        pdms.init(Services.get());
        pdms.addMissingDependency(dep1, actionId1);
        pdms.addMissingDependency(dep2, actionId2);
        pdms.addMissingDependency(dep3, actionId3);
        pdms.runCachePurgeWorker();

        assertNotNull((Collection<String>) pdms.getWaitingActions(dep1));
        assertNotNull((Collection<String>) pdms.getWaitingActions(dep2));
        assertNotNull((Collection<String>) pdms.getWaitingActions(dep3));

        List<String> deleteList = new ArrayList<String>();
        deleteList.add(actionId1);
        JPAService jpaService = Services.get().get(JPAService.class);
        jpaService.execute(new CoordActionsDeleteJPAExecutor(deleteList));
        pdms.runCachePurgeWorker();

        assertNull((Collection<String>) pdms.getWaitingActions(dep1));
        assertNotNull((Collection<String>) pdms.getWaitingActions(dep2));
        assertNotNull((Collection<String>) pdms.getWaitingActions(dep3));
        deleteList.clear();
        deleteList.add(actionId2);
        jpaService.execute(new CoordActionsDeleteJPAExecutor(deleteList));
        pdms.runCachePurgeWorker();
        assertNull((Collection<String>) pdms.getWaitingActions(dep1));
        assertNull((Collection<String>) pdms.getWaitingActions(dep2));
        assertNotNull((Collection<String>) pdms.getWaitingActions(dep3));
    }

}
