/**
 * 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.hcatalog.hbase.snapshot;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hcatalog.hbase.snapshot.lock.LockListener;
import org.apache.hcatalog.hbase.snapshot.lock.WriteLock;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs.Ids;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The service for providing revision management to Hbase tables.
 */
public class ZKBasedRevisionManager implements RevisionManager {

    private static final Logger LOG = LoggerFactory.getLogger(ZKBasedRevisionManager.class);
    private String zkHostList;
    private String baseDir;
    private ZKUtil zkUtil;
    private long writeTxnTimeout;


    /*
     * @see org.apache.hcatalog.hbase.snapshot.RevisionManager#initialize()
     */
    @Override
    public void initialize(Configuration conf) {
        conf = new Configuration(conf);
        if (conf.get(RMConstants.ZOOKEEPER_HOSTLIST) == null) {
            String zkHostList = conf.get(HConstants.ZOOKEEPER_QUORUM);
            int port = conf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT,
                HConstants.DEFAULT_ZOOKEPER_CLIENT_PORT);
            String[] splits = zkHostList.split(",");
            StringBuffer sb = new StringBuffer();
            for (String split : splits) {
                sb.append(split);
                sb.append(':');
                sb.append(port);
                sb.append(',');
            }
            sb.deleteCharAt(sb.length() - 1);
            conf.set(RMConstants.ZOOKEEPER_HOSTLIST, sb.toString());
        }
        this.zkHostList = conf.get(RMConstants.ZOOKEEPER_HOSTLIST);
        this.baseDir = conf.get(RMConstants.ZOOKEEPER_DATADIR);
        this.writeTxnTimeout = Long.parseLong(conf.get(RMConstants.WRITE_TRANSACTION_TIMEOUT));
    }

    /**
     * Open a ZooKeeper connection
     * @throws java.io.IOException
     */

    public void open() throws IOException {
        zkUtil = new ZKUtil(zkHostList, this.baseDir);
        zkUtil.createRootZNodes();
        LOG.info("Created root znodes for revision manager.");
    }

    /**
     * Close Zookeeper connection
     */
    public void close() {
        zkUtil.closeZKConnection();
    }

    private void checkInputParams(String table, List<String> families) {
        if (table == null) {
            throw new IllegalArgumentException(
                "The table name must be specified for reading.");
        }
        if (families == null || families.isEmpty()) {
            throw new IllegalArgumentException(
                "At least one column family should be specified for reading.");
        }
    }

    @Override
    public void createTable(String table, List<String> columnFamilies) throws IOException {
        zkUtil.createRootZNodes();
        zkUtil.setUpZnodesForTable(table, columnFamilies);
    }

    @Override
    public void dropTable(String table) throws IOException {
        zkUtil.deleteZNodes(table);
    }

    /* @param table
    /* @param families
    /* @param keepAlive
    /* @return
    /* @throws IOException
     * @see org.apache.hcatalog.hbase.snapshot.RevisionManager#beginWriteTransaction(java.lang.String, java.util.List, long)
     */
    public Transaction beginWriteTransaction(String table,
                                             List<String> families, long keepAlive) throws IOException {

        checkInputParams(table, families);
        zkUtil.setUpZnodesForTable(table, families);
        long nextId = zkUtil.nextId(table);
        long expireTimestamp = zkUtil.getTimeStamp();
        Transaction transaction = new Transaction(table, families, nextId,
            expireTimestamp);
        if (keepAlive != -1) {
            transaction.setKeepAlive(keepAlive);
        } else {
            transaction.setKeepAlive(writeTxnTimeout);
        }

        refreshTransactionList(transaction.getTableName());
        String lockPath = prepareLockNode(table);
        WriteLock wLock = new WriteLock(zkUtil.getSession(), lockPath,
            Ids.OPEN_ACL_UNSAFE);
        RMLockListener myLockListener = new RMLockListener();
        wLock.setLockListener(myLockListener);
        try {
            boolean lockGrabbed = wLock.lock();
            if (lockGrabbed == false) {
                //TO DO : Let this request queue up and try obtaining lock.
                throw new IOException(
                    "Unable to obtain lock while beginning transaction. "
                        + transaction.toString());
            } else {
                List<String> colFamilies = transaction.getColumnFamilies();
                FamilyRevision revisionData = transaction.getFamilyRevisionInfo();
                for (String cfamily : colFamilies) {
                    String path = PathUtil.getRunningTxnInfoPath(
                        baseDir, table, cfamily);
                    zkUtil.updateData(path, revisionData,
                        ZKUtil.UpdateMode.APPEND);
                }
            }
        } catch (KeeperException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } catch (InterruptedException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } finally {
            wLock.unlock();
        }

        return transaction;
    }

    /* @param table The table name.
    /* @param families The column families involved in the transaction.
    /* @return transaction The transaction which was started.
    /* @throws IOException
     * @see org.apache.hcatalog.hbase.snapshot.RevisionManager#beginWriteTransaction(java.lang.String, java.util.List)
     */
    public Transaction beginWriteTransaction(String table, List<String> families)
        throws IOException {
        return beginWriteTransaction(table, families, -1);
    }

    /**
     * This method commits a write transaction.
     * @param transaction The revision information associated with transaction.
     * @throws java.io.IOException
     */
    public void commitWriteTransaction(Transaction transaction) throws IOException {
        refreshTransactionList(transaction.getTableName());

        String lockPath = prepareLockNode(transaction.getTableName());
        WriteLock wLock = new WriteLock(zkUtil.getSession(), lockPath,
            Ids.OPEN_ACL_UNSAFE);
        RMLockListener myLockListener = new RMLockListener();
        wLock.setLockListener(myLockListener);
        try {
            boolean lockGrabbed = wLock.lock();
            if (lockGrabbed == false) {
                //TO DO : Let this request queue up and try obtaining lock.
                throw new IOException(
                    "Unable to obtain lock while commiting transaction. "
                        + transaction.toString());
            } else {
                String tableName = transaction.getTableName();
                List<String> colFamilies = transaction.getColumnFamilies();
                FamilyRevision revisionData = transaction.getFamilyRevisionInfo();
                for (String cfamily : colFamilies) {
                    String path = PathUtil.getRunningTxnInfoPath(
                        baseDir, tableName, cfamily);
                    zkUtil.updateData(path, revisionData,
                        ZKUtil.UpdateMode.REMOVE);
                }

            }
        } catch (KeeperException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } catch (InterruptedException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } finally {
            wLock.unlock();
        }
        LOG.info("Write Transaction committed: " + transaction.toString());
    }

    /**
     * This method aborts a write transaction.
     * @param transaction
     * @throws java.io.IOException
     */
    public void abortWriteTransaction(Transaction transaction) throws IOException {

        refreshTransactionList(transaction.getTableName());
        String lockPath = prepareLockNode(transaction.getTableName());
        WriteLock wLock = new WriteLock(zkUtil.getSession(), lockPath,
            Ids.OPEN_ACL_UNSAFE);
        RMLockListener myLockListener = new RMLockListener();
        wLock.setLockListener(myLockListener);
        try {
            boolean lockGrabbed = wLock.lock();
            if (lockGrabbed == false) {
                //TO DO : Let this request queue up and try obtaining lock.
                throw new IOException(
                    "Unable to obtain lock while aborting transaction. "
                        + transaction.toString());
            } else {
                String tableName = transaction.getTableName();
                List<String> colFamilies = transaction.getColumnFamilies();
                FamilyRevision revisionData = transaction
                    .getFamilyRevisionInfo();
                for (String cfamily : colFamilies) {
                    String path = PathUtil.getRunningTxnInfoPath(
                        baseDir, tableName, cfamily);
                    zkUtil.updateData(path, revisionData,
                        ZKUtil.UpdateMode.REMOVE);
                    path = PathUtil.getAbortInformationPath(baseDir,
                        tableName, cfamily);
                    zkUtil.updateData(path, revisionData,
                        ZKUtil.UpdateMode.APPEND);
                }

            }
        } catch (KeeperException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } catch (InterruptedException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } finally {
            wLock.unlock();
        }
        LOG.info("Write Transaction aborted: " + transaction.toString());
    }


    /* @param transaction
   /* @throws IOException
    * @see org.apache.hcatalog.hbase.snapshot.RevsionManager#keepAlive(org.apache.hcatalog.hbase.snapshot.Transaction)
    */
    public void keepAlive(Transaction transaction)
        throws IOException {

        refreshTransactionList(transaction.getTableName());
        transaction.keepAliveTransaction();
        String lockPath = prepareLockNode(transaction.getTableName());
        WriteLock wLock = new WriteLock(zkUtil.getSession(), lockPath,
            Ids.OPEN_ACL_UNSAFE);
        RMLockListener myLockListener = new RMLockListener();
        wLock.setLockListener(myLockListener);
        try {
            boolean lockGrabbed = wLock.lock();
            if (lockGrabbed == false) {
                //TO DO : Let this request queue up and try obtaining lock.
                throw new IOException(
                    "Unable to obtain lock for keep alive of transaction. "
                        + transaction.toString());
            } else {
                String tableName = transaction.getTableName();
                List<String> colFamilies = transaction.getColumnFamilies();
                FamilyRevision revisionData = transaction.getFamilyRevisionInfo();
                for (String cfamily : colFamilies) {
                    String path = PathUtil.getRunningTxnInfoPath(
                        baseDir, tableName, cfamily);
                    zkUtil.updateData(path, revisionData,
                        ZKUtil.UpdateMode.KEEP_ALIVE);
                }

            }
        } catch (KeeperException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } catch (InterruptedException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } finally {
            wLock.unlock();
        }

    }

    /* This method allows the user to create latest snapshot of a
    /* table.
    /* @param tableName The table whose snapshot is being created.
    /* @return TableSnapshot An instance of TableSnaphot
    /* @throws IOException
     * @see org.apache.hcatalog.hbase.snapshot.RevsionManager#createSnapshot(java.lang.String)
     */
    public TableSnapshot createSnapshot(String tableName) throws IOException {
        refreshTransactionList(tableName);
        long latestID = zkUtil.currentID(tableName);
        HashMap<String, Long> cfMap = new HashMap<String, Long>();
        List<String> columnFamilyNames = zkUtil.getColumnFamiliesOfTable(tableName);

        for (String cfName : columnFamilyNames) {
            String cfPath = PathUtil.getRunningTxnInfoPath(baseDir, tableName, cfName);
            List<FamilyRevision> tranxList = zkUtil.getTransactionList(cfPath);
            long version;
            if (!tranxList.isEmpty()) {
                Collections.sort(tranxList);
                // get the smallest running Transaction ID
                long runningVersion = tranxList.get(0).getRevision();
                version = runningVersion - 1;
            } else {
                version = latestID;
            }
            cfMap.put(cfName, version);
        }

        TableSnapshot snapshot = new TableSnapshot(tableName, cfMap, latestID);
        LOG.debug("Created snapshot For table: " + tableName + " snapshot: " + snapshot);
        return snapshot;
    }

    /* This method allows the user to create snapshot of a
    /* table with a given revision number.
    /* @param tableName
    /* @param revision
    /* @return TableSnapshot
    /* @throws IOException
     * @see org.apache.hcatalog.hbase.snapshot.RevsionManager#createSnapshot(java.lang.String, long)
     */
    public TableSnapshot createSnapshot(String tableName, long revision) throws IOException {

        long currentID = zkUtil.currentID(tableName);
        if (revision > currentID) {
            throw new IOException(
                "The revision specified in the snapshot is higher than the current revision of the table.");
        }
        refreshTransactionList(tableName);
        HashMap<String, Long> cfMap = new HashMap<String, Long>();
        List<String> columnFamilies = zkUtil.getColumnFamiliesOfTable(tableName);

        for (String cf : columnFamilies) {
            cfMap.put(cf, revision);
        }

        return new TableSnapshot(tableName, cfMap, revision);
    }

    /**
     * Get the list of in-progress Transactions for a column family
     * @param table the table name
     * @param columnFamily the column family name
     * @return a list of in-progress WriteTransactions
     * @throws java.io.IOException
     */
    List<FamilyRevision> getRunningTransactions(String table,
                                                String columnFamily) throws IOException {
        String path = PathUtil.getRunningTxnInfoPath(baseDir, table,
            columnFamily);
        return zkUtil.getTransactionList(path);
    }

    @Override
    public List<FamilyRevision> getAbortedWriteTransactions(String table,
                                                            String columnFamily) throws IOException {
        String path = PathUtil.getAbortInformationPath(baseDir, table, columnFamily);
        return zkUtil.getTransactionList(path);
    }

    private void refreshTransactionList(String tableName) throws IOException {
        String lockPath = prepareLockNode(tableName);
        WriteLock wLock = new WriteLock(zkUtil.getSession(), lockPath,
            Ids.OPEN_ACL_UNSAFE);
        RMLockListener myLockListener = new RMLockListener();
        wLock.setLockListener(myLockListener);
        try {
            boolean lockGrabbed = wLock.lock();
            if (lockGrabbed == false) {
                //TO DO : Let this request queue up and try obtaining lock.
                throw new IOException(
                    "Unable to obtain lock while refreshing transactions of table "
                        + tableName + ".");
            } else {
                List<String> cfPaths = zkUtil
                    .getColumnFamiliesOfTable(tableName);
                for (String cf : cfPaths) {
                    String runningDataPath = PathUtil.getRunningTxnInfoPath(
                        baseDir, tableName, cf);
                    zkUtil.refreshTransactions(runningDataPath);
                }

            }
        } catch (KeeperException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } catch (InterruptedException e) {
            throw new IOException("Exception while obtaining lock.", e);
        } finally {
            wLock.unlock();
        }

    }

    private String prepareLockNode(String tableName) throws IOException {
        String txnDataPath = PathUtil.getTxnDataPath(this.baseDir, tableName);
        String lockPath = PathUtil.getLockManagementNode(txnDataPath);
        zkUtil.ensurePathExists(lockPath, null, Ids.OPEN_ACL_UNSAFE,
            CreateMode.PERSISTENT);
        return lockPath;
    }

    /*
     * This class is a listener class for the locks used in revision management.
     * TBD: Use the following class to signal that that the lock is actually
     * been granted.
     */
    class RMLockListener implements LockListener {

        /*
         * @see org.apache.hcatalog.hbase.snapshot.lock.LockListener#lockAcquired()
         */
        @Override
        public void lockAcquired() {

        }

        /*
         * @see org.apache.hcatalog.hbase.snapshot.lock.LockListener#lockReleased()
         */
        @Override
        public void lockReleased() {

        }

    }


}
