Package azkaban.flow

Source Code of azkaban.flow.CachingFlowManager

/*
* Copyright 2010 LinkedIn, Inc
*
* Licensed 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 azkaban.flow;

import azkaban.common.utils.Props;
import azkaban.flow.ExecutableFlow;
import azkaban.flow.Flow;
import azkaban.jobs.Status;

import org.apache.log4j.Logger;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* A FlowManager that caches ExecutableFlows.
*
* That is, if "createNewExecutableFlow()" generated a Flow with id 2, subsequent calls to loadExecutableFlow(2) would
* return the same instance.
*/
public class CachingFlowManager implements FlowManager
{
    private static final Logger log = Logger.getLogger(CachingFlowManager.class);

    private final FlowManager baseManager;
    private final Map<String, FlowExecutionHolder> flowCache;

    public CachingFlowManager(FlowManager baseManager, final int cacheSize)
    {
        this.baseManager = baseManager;

        this.flowCache = Collections.synchronizedMap(
                new LinkedHashMap<String, FlowExecutionHolder>((int) (cacheSize * 1.5), 0.75f, true){
                    @Override
                    protected boolean removeEldestEntry(Map.Entry<String, FlowExecutionHolder> eldest)
                    {
                        final boolean tooManyElements = super.size() > cacheSize;

                        if (tooManyElements) {
                            final Status status = eldest.getValue().getFlow().getStatus();

                            if (status != Status.RUNNING) {
                                return true;
                            }
                            else {
                                log.warn(String.format(
                                        "Cache is at size[%s] and should have evicted an entry, but the oldest entry wasn't completed[%s].  Perhaps the cache size is too small",
                                        super.size(),
                                        status
                                ));
                            }
                        }

                        return false;
                    }
                }
        );
    }

    public boolean hasFlow(String name)
    {
        return baseManager.hasFlow(name);
    }

    public Flow getFlow(String name)
    {
        return baseManager.getFlow(name);
    }

    public Collection<Flow> getFlows()
    {
        return baseManager.getFlows();
    }

    public Set<String> getRootFlowNames()
    {
        return baseManager.getRootFlowNames();
    }

    @Override
    public Iterator<Flow> iterator()
    {
        return baseManager.iterator();
    }

    public ExecutableFlow createNewExecutableFlow(String name)
    {
        final ExecutableFlow retVal = baseManager.createNewExecutableFlow(name);

        return new WrappingExecutableFlow(retVal){
            @Override
            public void execute(Props parentProperties, FlowCallback callback) {

                if (! flowCache.containsKey(getId())) {
                    addToCache(
                            new FlowExecutionHolder(
                                    retVal,
                                    parentProperties
                            )
                    );
                }

                super.execute(parentProperties, callback);
            }
        };
    }

    public long getNextId()
    {
        return baseManager.getNextId();
    }

    public long getCurrMaxId()
    {
        return baseManager.getCurrMaxId();
    }

    public FlowExecutionHolder saveExecutableFlow(FlowExecutionHolder holder)
    {
        return baseManager.saveExecutableFlow(holder);
    }

    public FlowExecutionHolder loadExecutableFlow(long id)
    {
        final FlowExecutionHolder executableFlow = flowCache.get(String.valueOf(id));
        if (executableFlow != null) {
            return executableFlow;
        }

        final FlowExecutionHolder retVal = baseManager.loadExecutableFlow(id);

        addToCache(retVal);

        return retVal;
    }

    public void reload()
    {
        baseManager.reload();
    }

    private void addToCache(FlowExecutionHolder retVal)
    {
        if (retVal == null || retVal.getFlow() == null) {
            return;
        }

        if (flowCache.put(retVal.getFlow().getId(), retVal) != null) {
            throw new IllegalStateException(
                    String.format(
                            "Attempted to add object to the cache but the id[%s] already existed.  Flow was [%s]",
                            retVal.getFlow().getId(),
                            retVal
                    )
            );
        }
    }

  @Override
  public List<String> getFolders() {
    return baseManager.getFolders();
  }

  @Override
  public List<String> getRootNamesByFolder(String folder) {
    return baseManager.getRootNamesByFolder(folder);
  }
}
TOP

Related Classes of azkaban.flow.CachingFlowManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.