org.apache.falcon.state.store.jdbc.JDBCStateStore.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.falcon.state.store.jdbc.JDBCStateStore.java

Source

/**
 * 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.falcon.state.store.jdbc;

import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.falcon.entity.v0.Entity;
import org.apache.falcon.exception.StateStoreException;
import org.apache.falcon.execution.ExecutionInstance;
import org.apache.falcon.persistence.EntityBean;
import org.apache.falcon.persistence.InstanceBean;
import org.apache.falcon.persistence.PersistenceConstants;
import org.apache.falcon.state.EntityClusterID;
import org.apache.falcon.state.EntityID;
import org.apache.falcon.state.EntityState;
import org.apache.falcon.state.ID;
import org.apache.falcon.state.InstanceID;
import org.apache.falcon.state.InstanceState;
import org.apache.falcon.state.store.AbstractStateStore;
import org.apache.falcon.state.store.StateStore;
import org.apache.falcon.service.FalconJPAService;
import org.apache.falcon.util.StateStoreProperties;
import org.joda.time.DateTime;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Persistent Data Store for Entities and Instances.
 */
public final class JDBCStateStore extends AbstractStateStore {

    private static final StateStore STORE = new JDBCStateStore();
    private static final String DEBUG = "debug";

    private JDBCStateStore() {
    }

    public static StateStore get() {
        return STORE;
    }

    @Override
    public void clear() throws StateStoreException {
        if (!isModeDebug()) {
            throw new UnsupportedOperationException("Clear Method not supported");
        }
        deleteExecutionInstances();
        deleteEntities();
    }

    @Override
    public void putEntity(EntityState entityState) throws StateStoreException {
        EntityID entityID = new EntityID(entityState.getEntity());
        String key = entityID.getKey();
        if (entityExists(entityID)) {
            throw new StateStoreException("Entity with key, " + key + " already exists.");
        }
        EntityBean entityBean = null;
        try {
            entityBean = BeanMapperUtil.convertToEntityBean(entityState);
            EntityManager entityManager = getEntityManager();
            beginTransaction(entityManager);
            entityManager.persist(entityBean);
            commitAndCloseTransaction(entityManager);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }
    }

    @Override
    public EntityState getEntity(EntityID entityID) throws StateStoreException {
        EntityState entityState = getEntityByKey(entityID);
        if (entityState == null) {
            throw new StateStoreException("Entity with key, " + entityID + " does not exist.");
        }
        return entityState;
    }

    private EntityState getEntityByKey(EntityID id) throws StateStoreException {
        EntityBean entityBean = getEntityBean(id);
        if (entityBean == null) {
            return null;
        }
        try {
            return BeanMapperUtil.convertToEntityState(entityBean);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }
    }

    private EntityBean getEntityBean(EntityID id) {
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_ENTITY);
        q.setParameter("id", id.getKey());
        List result = q.getResultList();
        entityManager.close();
        if (result.isEmpty()) {
            return null;
        }
        return ((EntityBean) result.get(0));
    }

    @Override
    public boolean entityExists(EntityID entityID) throws StateStoreException {
        return getEntityByKey(entityID) == null ? false : true;
    }

    @Override
    public Collection<Entity> getEntities(EntityState.STATE state) throws StateStoreException {
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_ENTITY_FOR_STATE);
        q.setParameter("state", state.toString());
        List result = q.getResultList();
        entityManager.close();
        return BeanMapperUtil.convertToEntities(result);
    }

    @Override
    public Collection<EntityState> getAllEntities() throws StateStoreException {
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_ENTITIES);
        List result = q.getResultList();
        entityManager.close();
        try {
            return BeanMapperUtil.convertToEntityState(result);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }
    }

    @Override
    public void updateEntity(EntityState entityState) throws StateStoreException {
        EntityID entityID = new EntityID(entityState.getEntity());
        if (!entityExists(entityID)) {
            throw new StateStoreException("Entity with key, " + entityID + " doesn't exists.");
        }
        EntityManager entityManager = getEntityManager();
        beginTransaction(entityManager);
        Query q = entityManager.createNamedQuery(PersistenceConstants.UPDATE_ENTITY);
        q.setParameter("id", entityID.getKey());
        if (entityState.getCurrentState() != null) {
            q.setParameter("state", entityState.getCurrentState().toString());
        }
        q.setParameter("type", entityState.getEntity().getEntityType().toString());
        q.setParameter("name", entityState.getEntity().getName());
        q.executeUpdate();
        commitAndCloseTransaction(entityManager);
    }

    @Override
    public void deleteEntity(EntityID entityID) throws StateStoreException {
        if (!entityExists(entityID)) {
            throw new StateStoreException("Entity with key, " + entityID.getKey() + " does not exist.");
        }
        EntityManager entityManager = getEntityManager();
        beginTransaction(entityManager);
        Query q = entityManager.createNamedQuery(PersistenceConstants.DELETE_ENTITY);
        q.setParameter("id", entityID.getKey());
        q.executeUpdate();
        commitAndCloseTransaction(entityManager);
    }

    @Override
    public void deleteEntities() throws StateStoreException {
        if (!isModeDebug()) {
            throw new UnsupportedOperationException("Delete Entities Table not supported");
        }
        EntityManager entityManager = getEntityManager();
        beginTransaction(entityManager);
        Query q = entityManager.createNamedQuery(PersistenceConstants.DELETE_ENTITIES);
        q.executeUpdate();
        commitAndCloseTransaction(entityManager);
    }

    @Override
    public boolean isEntityCompleted(EntityID entityId) {
        // ToDo need to implement this, currently returning false.
        return false;
    }

    @Override
    public void putExecutionInstance(InstanceState instanceState) throws StateStoreException {
        InstanceID instanceID = new InstanceID(instanceState.getInstance());
        if (executionInstanceExists(instanceID)) {
            throw new StateStoreException("Instance with key, " + instanceID + " already exists.");
        }
        try {
            InstanceBean instanceBean = BeanMapperUtil.convertToInstanceBean(instanceState);
            EntityBean entityBean = getEntityBean(new InstanceID(instanceState.getInstance()).getEntityID());
            instanceBean.setEntityBean(entityBean);
            EntityManager entityManager = getEntityManager();
            beginTransaction(entityManager);
            entityManager.persist(instanceBean);
            commitAndCloseTransaction(entityManager);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }
    }

    @Override
    public InstanceState getExecutionInstance(InstanceID instanceId) throws StateStoreException {
        InstanceState instanceState = getExecutionInstanceByKey(instanceId);
        if (instanceState == null) {
            throw new StateStoreException("Instance with key, " + instanceId.toString() + " does not exist.");
        }
        return instanceState;
    }

    private InstanceState getExecutionInstanceByKey(ID instanceKey) throws StateStoreException {
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_INSTANCE);
        q.setParameter("id", instanceKey.toString());
        List result = q.getResultList();
        entityManager.close();
        if (result.isEmpty()) {
            return null;
        }
        try {
            InstanceBean instanceBean = (InstanceBean) (result.get(0));
            return BeanMapperUtil.convertToInstanceState(instanceBean);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }
    }

    @Override
    public InstanceState getExecutionInstance(String externalID) throws StateStoreException {
        if (StringUtils.isEmpty(externalID)) {
            throw new StateStoreException("External ID for retrieving instance cannot be null or empty");
        }
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_INSTANCE_FOR_EXTERNAL_ID);
        q.setParameter("externalID", externalID);
        List result = q.getResultList();
        entityManager.close();
        if (result.isEmpty()) {
            return null;
        }
        try {
            InstanceBean instanceBean = (InstanceBean) (result.get(0));
            return BeanMapperUtil.convertToInstanceState(instanceBean);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }

    }

    @Override
    public void updateExecutionInstance(InstanceState instanceState) throws StateStoreException {
        InstanceID id = new InstanceID(instanceState.getInstance());
        String key = id.toString();
        if (!executionInstanceExists(id)) {
            throw new StateStoreException("Instance with key, " + key + " does not exist.");
        }
        EntityManager entityManager = getEntityManager();
        beginTransaction(entityManager);
        Query q = entityManager.createNamedQuery(PersistenceConstants.UPDATE_INSTANCE);
        ExecutionInstance instance = instanceState.getInstance();
        q.setParameter("id", key);
        q.setParameter("cluster", instance.getCluster());
        q.setParameter("externalID", instance.getExternalID());
        q.setParameter("instanceTime", new Timestamp(instance.getInstanceTime().getMillis()));
        q.setParameter("creationTime", new Timestamp(instance.getCreationTime().getMillis()));
        if (instance.getActualEnd() != null) {
            q.setParameter("actualEndTime", new Timestamp(instance.getActualEnd().getMillis()));
        }
        q.setParameter("currentState", instanceState.getCurrentState().toString());
        if (instance.getActualStart() != null) {
            q.setParameter("actualStartTime", new Timestamp(instance.getActualStart().getMillis()));
        }
        q.setParameter("instanceSequence", instance.getInstanceSequence());
        if (instanceState.getInstance().getAwaitingPredicates() != null
                && !instanceState.getInstance().getAwaitingPredicates().isEmpty()) {
            try {
                q.setParameter("awaitedPredicates", BeanMapperUtil.getAwaitedPredicates(instanceState));
            } catch (IOException e) {
                throw new StateStoreException(e);
            }
        }
        if (instance.getProperties() != null && !instance.getProperties().isEmpty()) {
            try {
                q.setParameter("properties", BeanMapperUtil.getProperties(instanceState));
            } catch (IOException e) {
                throw new StateStoreException(e);
            }
        }
        q.executeUpdate();
        commitAndCloseTransaction(entityManager);
    }

    @Override
    public Collection<InstanceState> getAllExecutionInstances(Entity entity, String cluster)
            throws StateStoreException {
        EntityClusterID id = new EntityClusterID(entity, cluster);
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_INSTANCES_FOR_ENTITY_CLUSTER);
        q.setParameter("entityId", id.getEntityID().getKey());
        q.setParameter("cluster", cluster);
        List result = q.getResultList();
        entityManager.close();
        try {
            return BeanMapperUtil.convertToInstanceState(result);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }
    }

    @Override
    public Collection<InstanceState> getExecutionInstances(Entity entity, String cluster,
            Collection<InstanceState.STATE> states) throws StateStoreException {
        EntityClusterID entityClusterID = new EntityClusterID(entity, cluster);
        String entityKey = entityClusterID.getEntityID().getKey();
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_INSTANCES_FOR_ENTITY_CLUSTER_FOR_STATES);
        q.setParameter("entityId", entityKey);
        q.setParameter("cluster", cluster);
        List<String> instanceStates = new ArrayList<>();
        for (InstanceState.STATE state : states) {
            instanceStates.add(state.toString());
        }
        q.setParameter("currentState", instanceStates);
        List result = q.getResultList();
        entityManager.close();
        try {
            return BeanMapperUtil.convertToInstanceState(result);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }
    }

    @Override
    public Collection<InstanceState> getExecutionInstances(EntityClusterID id,
            Collection<InstanceState.STATE> states) throws StateStoreException {
        String entityKey = id.getEntityID().getKey();
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_INSTANCES_FOR_ENTITY_FOR_STATES);
        q.setParameter("entityId", entityKey);
        List<String> instanceStates = new ArrayList<>();
        for (InstanceState.STATE state : states) {
            instanceStates.add(state.toString());
        }
        q.setParameter("currentState", instanceStates);
        List result = q.getResultList();
        entityManager.close();
        try {
            return BeanMapperUtil.convertToInstanceState(result);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }
    }

    @Override
    public Map<InstanceState.STATE, Long> getExecutionInstanceSummary(Entity entity, String cluster, DateTime start,
            DateTime end) throws StateStoreException {
        String entityKey = new EntityClusterID(entity, cluster).getEntityID().getKey();
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_INSTANCE_SUMMARY_BY_STATE_WITH_RANGE);
        q.setParameter("entityId", entityKey);
        q.setParameter("cluster", cluster);
        q.setParameter("startTime", new Timestamp(start.getMillis()));
        q.setParameter("endTime", new Timestamp(end.getMillis()));
        List result = q.getResultList();
        entityManager.close();

        return BeanMapperUtil.getInstanceStateSummary(result);
    }

    @Override
    public Collection<InstanceState> getExecutionInstances(Entity entity, String cluster,
            Collection<InstanceState.STATE> states, DateTime start, DateTime end) throws StateStoreException {
        String entityKey = new EntityClusterID(entity, cluster).getEntityID().getKey();
        EntityManager entityManager = getEntityManager();
        Query q = entityManager
                .createNamedQuery(PersistenceConstants.GET_INSTANCES_FOR_ENTITY_CLUSTER_FOR_STATES_WITH_RANGE);
        q.setParameter("entityId", entityKey);
        List<String> instanceStates = new ArrayList<>();
        for (InstanceState.STATE state : states) {
            instanceStates.add(state.toString());
        }
        q.setParameter("currentState", instanceStates);
        q.setParameter("startTime", new Timestamp(start.getMillis()));
        q.setParameter("endTime", new Timestamp(end.getMillis()));
        q.setParameter("cluster", cluster);
        List result = q.getResultList();
        entityManager.close();
        try {
            return BeanMapperUtil.convertToInstanceState(result);
        } catch (IOException e) {
            throw new StateStoreException(e);
        }
    }

    @Override
    public InstanceState getLastExecutionInstance(Entity entity, String cluster) throws StateStoreException {
        String key = new EntityClusterID(entity, cluster).getEntityID().getKey();
        EntityManager entityManager = getEntityManager();
        Query q = entityManager.createNamedQuery(PersistenceConstants.GET_LAST_INSTANCE_FOR_ENTITY_CLUSTER);
        q.setParameter("entityId", key);
        q.setParameter("cluster", cluster);
        q.setMaxResults(1);
        List result = q.getResultList();
        entityManager.close();
        if (!result.isEmpty()) {
            try {
                return BeanMapperUtil.convertToInstanceState((InstanceBean) result.get(0));
            } catch (IOException e) {
                throw new StateStoreException(e);
            }
        }
        return null;
    }

    @Override
    public boolean executionInstanceExists(InstanceID instanceKey) throws StateStoreException {
        return getExecutionInstanceByKey(instanceKey) == null ? false : true;
    }

    @Override
    public void deleteExecutionInstance(InstanceID instanceID) throws StateStoreException {
        String instanceKey = instanceID.toString();
        if (!executionInstanceExists(instanceID)) {
            throw new StateStoreException("Instance with key, " + instanceKey + " does not exist.");
        }
        EntityManager entityManager = getEntityManager();
        beginTransaction(entityManager);
        Query q = entityManager.createNamedQuery(PersistenceConstants.DELETE_INSTANCE);
        q.setParameter("id", instanceKey);
        q.executeUpdate();
        commitAndCloseTransaction(entityManager);
    }

    @Override
    public void deleteExecutionInstances(EntityID entityID) {
        String entityKey = entityID.getKey();
        EntityManager entityManager = getEntityManager();
        beginTransaction(entityManager);
        Query q = entityManager.createNamedQuery(PersistenceConstants.DELETE_INSTANCE_FOR_ENTITY);
        q.setParameter("entityId", entityKey);
        q.executeUpdate();
        commitAndCloseTransaction(entityManager);
    }

    @Override
    public void deleteExecutionInstances() {
        if (!isModeDebug()) {
            throw new UnsupportedOperationException("Delete Instances Table not supported");
        }
        EntityManager entityManager = getEntityManager();
        beginTransaction(entityManager);
        Query q = entityManager.createNamedQuery(PersistenceConstants.DELETE_INSTANCES_TABLE);
        q.executeUpdate();
        commitAndCloseTransaction(entityManager);
    }

    // Debug enabled for test cases
    private boolean isModeDebug() {
        return DEBUG.equals(StateStoreProperties.get().getProperty("domain")) ? true : false;
    }

    private void commitAndCloseTransaction(EntityManager entityManager) {
        entityManager.getTransaction().commit();
        entityManager.close();
    }

    private void beginTransaction(EntityManager entityManager) {
        entityManager.getTransaction().begin();
    }

    private EntityManager getEntityManager() {
        return FalconJPAService.get().getEntityManager();
    }

}