Package xbird.xquery.ext.grid

Source Code of xbird.xquery.ext.grid.DispatchQueryExecTask

/*
* @(#)$Id$
*
* Copyright 2006-2008 Makoto YUI
*
* 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.
*
* Contributors:
*     Makoto YUI - initial implementation
*/
package xbird.xquery.ext.grid;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import gridool.GridConfiguration;
import gridool.GridException;
import gridool.GridJob;
import gridool.GridKernel;
import gridool.GridNode;
import gridool.GridTask;
import gridool.annotation.DirectoryResource;
import gridool.annotation.GridConfigResource;
import gridool.annotation.GridKernelResource;
import gridool.communication.payload.GridNodeInfo;
import gridool.construct.GridTaskAdapter;
import gridool.directory.LocalDirectory;
import gridool.locking.LockManager;
import gridool.routing.GridNodeSelector;
import gridool.routing.GridTaskRouter;
import gridool.util.GridUtils;
import xbird.storage.DbException;
import xbird.util.struct.Pair;
import xbird.xquery.dm.value.Item;
import xbird.xquery.dm.value.Sequence;
import xbird.xquery.expr.XQExpression;
import xbird.xquery.expr.var.BindingVariable;

/**
*
* <DIV lang="en"></DIV>
* <DIV lang="ja"></DIV>
*
* @author Makoto YUI (yuin405+xbird@gmail.com)
*/
public final class DispatchQueryExecTask extends GridTaskAdapter {
    private static final long serialVersionUID = 5561645251880268369L;
    private static final Log LOG = LogFactory.getLog(DispatchQueryExecTask.class);

    private final BindingVariable bindingVar;
    private final XQExpression bodyExpr;
    private final List<String> relativePaths;
    private final List<GridNode> excludeNodeList;
    private final boolean redirectable;

    // ----------------------------------------
    // injected resources

    @GridKernelResource
    private transient GridKernel grid;
    @GridConfigResource
    private transient GridConfiguration config;
    @DirectoryResource
    private transient LocalDirectory directory;

    // ----------------------------------------

    @SuppressWarnings("unchecked")
    public DispatchQueryExecTask(GridJob job, BindingVariable bindingVar, XQExpression bodyExpr, List<String> relativePaths, boolean redirectable) {
        super(job, true);
        assert (bindingVar != null);
        assert (bodyExpr != null);
        assert (relativePaths != null);
        this.bindingVar = bindingVar;
        this.bodyExpr = bodyExpr;
        this.relativePaths = relativePaths;
        this.excludeNodeList = new ArrayList<GridNode>(2);
        this.redirectable = redirectable;
    }

    @Override
    public boolean isAsyncTask() {
        return false;
    }

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

    public boolean isRedirectable() {
        return redirectable;
    }

    public BindingVariable getBindingVariable() {
        return bindingVar;
    }

    public XQExpression getBodyExpression() {
        return bodyExpr;
    }

    public List<String> getRelativePaths() {
        return relativePaths;
    }

    @Override
    public Sequence<? extends Item> execute() throws GridException {
        final Future<Sequence<? extends Item>> future = grid.execute(QueryExecJob.class, this);
        try {
            return future.get();
        } catch (InterruptedException ie) {
            LOG.error(ie.getMessage());
            throw new GridException(ie.getMessage(), ie);
        } catch (ExecutionException ee) {
            LOG.error(ee.getMessage());
            throw new GridException(ee.getMessage(), ee);
        }
    }

    /**
     * @see QueryExecJob#map(gridool.routing.GridTaskRouter, DispatchQueryExecTask)
     */
    public Map<GridTask, GridNode> mapQueryTask(QueryExecJob execJob) throws GridException {
        checkInjectedResources();

        final GridNodeInfo localNode = GridUtils.getLocalNode(config);
        if(!excludeNodeList.contains(localNode)) {
            excludeNodeList.add(localNode);
        }
        final GridNodeSelector nodeSelector = config.getNodeSelector();
        final LockManager lockManager = directory.getLockManager();

        final Map<GridNode, List<String>> assignMap = new HashMap<GridNode, List<String>>(relativePaths.size());
        final List<Pair<String, Lock>> localExecResources = new ArrayList<Pair<String, Lock>>(relativePaths.size());

        int totalLocked = 0;
        for(String path : relativePaths) {
            ReadWriteLock lock = lockManager.obtainLock(path);
            final Lock rlock = lock.readLock();
            if(rlock.tryLock()) {
                localExecResources.add(new Pair<String, Lock>(path, rlock));
            } else {
                totalLocked++;
                final List<GridNode> replicatedNodes;
                try {
                    replicatedNodes = directory.exactSearch(path, excludeNodeList);
                } catch (DbException e) {
                    LOG.error(e.getMessage());
                    throw new GridException("Exception caused while lookup: " + path, e);
                }
                if(replicatedNodes == null || replicatedNodes.isEmpty()) {
                    throw new GridException("No replicated document found for path: " + path);
                }
                // TODO Select a node that least recently used for write requests.
                GridNode node = nodeSelector.selectNode(replicatedNodes, this, config);
                assert (node != null);
                List<String> mappedPaths = assignMap.get(node);
                if(mappedPaths == null) {
                    mappedPaths = new ArrayList<String>(16);
                    assignMap.put(node, mappedPaths);
                }
                mappedPaths.add(path);
            }
        }

        final Map<GridTask, GridNode> map = new IdentityHashMap<GridTask, GridNode>(assignMap.size() + 1);
        for(Map.Entry<GridNode, List<String>> e : assignMap.entrySet()) {
            GridNode node = e.getKey();
            List<String> mappedPaths = e.getValue();
            DispatchQueryExecTask dispatchTask = new DispatchQueryExecTask(execJob, bindingVar, bodyExpr, mappedPaths, true);
            map.put(dispatchTask, node);
        }
        if(!localExecResources.isEmpty()) {
            boolean doForwarding = redirectable;
            LocalQueryExecTask localTask = new LocalQueryExecTask(execJob, bindingVar, bodyExpr, localExecResources, doForwarding);
            map.put(localTask, localNode);
        }

        if(LOG.isInfoEnabled()) {
            LOG.info("DispatchQueryExecTask is mapped to " + assignMap.size()
                    + " DispatchQueryExecTask and " + (localExecResources.isEmpty() ? '0' : '1')
                    + " LocalQueryExecTask (" + localExecResources.size()
                    + " localExecResources), " + totalLocked + " documents are write-locked");
        }
        return map;
    }

    private void checkInjectedResources() {
        if(config == null) {
            throw new IllegalStateException("GridConfiguration is not injected");
        }
        if(directory == null) {
            throw new IllegalStateException("LocalDirectory is not injected");
        }
    }

    @Override
    public List<GridNode> listFailoverCandidates(GridTask task, GridTaskRouter router) {
        GridNode[] liveNodes = router.getAllNodes();
        return GridUtils.selectSuperNodes(liveNodes);
    }

}
TOP

Related Classes of xbird.xquery.ext.grid.DispatchQueryExecTask

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.