Java tutorial
/* * @(#)$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.io.File; import java.io.Serializable; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.Lock; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import xbird.engine.remote.RemoteSequence; import xbird.engine.remote.ThrottedRemoteSequenceProxy; import gridool.GridException; import gridool.GridJob; import gridool.construct.GridTaskAdapter; import xbird.storage.DbCollection; import xbird.util.io.FileUtils; import xbird.util.net.TimeoutSocketProdiver; import xbird.util.struct.Pair; import xbird.xquery.XQueryException; import xbird.xquery.dm.dtm.IDocumentTable; import xbird.xquery.dm.dtm.LazyDTMDocument; import xbird.xquery.dm.instance.DocumentTableModel.DTMDocument; import xbird.xquery.dm.value.Item; import xbird.xquery.dm.value.Sequence; import xbird.xquery.dm.value.sequence.MarshalledSequence; import xbird.xquery.dm.value.sequence.NodeSequence; import xbird.xquery.dm.value.sequence.ValueSequence; import xbird.xquery.expr.XQExpression; import xbird.xquery.expr.var.BindingVariable; import xbird.xquery.meta.DynamicContext; /** * * <DIV lang="en"></DIV> * <DIV lang="ja"></DIV> * * @author Makoto YUI (yuin405+xbird@gmail.com) */ public final class LocalQueryExecTask extends GridTaskAdapter { private static final long serialVersionUID = -1356142633700786830L; private static final Log LOG = LogFactory.getLog(LocalQueryExecTask.class); private static final boolean queryShipping = !Boolean.getBoolean("gridool.query.data_shipping"); private final BindingVariable bindingVar; private final XQExpression bodyExpr; private final List<Pair<String, Lock>> relativePaths; private final boolean forwardingEnabled; @SuppressWarnings("unchecked") public LocalQueryExecTask(GridJob job, BindingVariable bindingVar, XQExpression bodyExpr, List<Pair<String, Lock>> relativePaths, boolean doForwarding) { super(job, false); this.bindingVar = bindingVar; this.bodyExpr = bodyExpr; this.relativePaths = relativePaths; this.forwardingEnabled = doForwarding; } @Override public boolean isAsyncTask() { return false; } @Override public Serializable execute() throws GridException { NodeSequence<DTMDocument> docs = listDocuments(relativePaths); assert (docs != null); bindingVar.allocateResult(docs, DynamicContext.DUMMY); final Sequence<? extends Item> result; try { result = bodyExpr.eval(ValueSequence.EMPTY_SEQUENCE, DynamicContext.DUMMY); } catch (XQueryException e) { throw new GridException(e); } return wrapResult(result, this, forwardingEnabled, queryShipping); } public static NodeSequence<DTMDocument> listDocuments(List<Pair<String, Lock>> relativePaths) throws GridException { final List<DTMDocument> docList = new ArrayList<DTMDocument>(relativePaths.size()); final Map<String, List<Pair<String, Lock>>> cfmap = mapFilesToCollections(relativePaths); for (Map.Entry<String, List<Pair<String, Lock>>> e : cfmap.entrySet()) { final String colpath = e.getKey(); final List<Pair<String, Lock>> fileResources = e.getValue(); DbCollection col = DbCollection.getCollection(colpath); File colDir = col.getDirectory(); if (!colDir.exists()) { throw new GridException("Collection not found: " + colpath); } for (Pair<String, Lock> rsc : fileResources) { String fname = rsc.getFirst(); File docFile = new File(colDir, fname + IDocumentTable.DTM_SEGMENT_FILE_SUFFIX); if (!docFile.exists()) { throw new GridException("Document not found: " + docFile.getAbsolutePath()); } LazyDTMDocument doc = new LazyDTMDocument(fname, col, DynamicContext.DUMMY); Lock lock = rsc.getSecond(); assert (lock != null); doc.setLock(lock); docList.add(doc); } } return new NodeSequence<DTMDocument>(docList, DynamicContext.DUMMY); } private static Map<String, List<Pair<String, Lock>>> mapFilesToCollections(List<Pair<String, Lock>> paths) { if (paths == null) { throw new IllegalStateException(); } final Map<String, List<Pair<String, Lock>>> map = new HashMap<String, List<Pair<String, Lock>>>(); for (Pair<String, Lock> rsc : paths) { String path = rsc.getFirst(); String colPath = FileUtils.dirName(path, '/'); List<Pair<String, Lock>> files = map.get(colPath); if (files == null) { files = new ArrayList<Pair<String, Lock>>(12); map.put(colPath, files); } String fileName = FileUtils.basename(path); rsc.setFirst(fileName); files.add(rsc); } return map; } @SuppressWarnings("unchecked") private static Sequence wrapResult(final Sequence result, final LocalQueryExecTask task, final boolean doForwarding, final boolean queryShipping) { if (doForwarding) { if (queryShipping) {// TODO take CPU usage into consideration if (LOG.isInfoEnabled()) { LOG.info("Response method for a task [" + task.getTaskId() + "]: QueryShipping"); } final ThrottedRemoteSequenceProxy remote = new ThrottedRemoteSequenceProxy(result); try { UnicastRemoteObject.exportObject(remote, 0, TimeoutSocketProdiver.createClientSocketFactory(), TimeoutSocketProdiver.createServerSocketFactory()); } catch (RemoteException e) { throw new IllegalStateException("failed exporting result sequence", e); } final RemoteSequence ret = new RemoteSequence(remote, result.getType()); new Thread(remote, "QueryTask[" + task.getTaskId() + "]#AsyncQueryProcessor").start(); return ret; } else { if (LOG.isInfoEnabled()) { LOG.info("Response method for a task [" + task.getTaskId() + "]: DataShipping"); } MarshalledSequence seq = new MarshalledSequence(result, DynamicContext.DUMMY); seq.setRemotePaging(true); return seq; } } else { if (LOG.isInfoEnabled()) { LOG.info("Response method for a task [" + task.getTaskId() + "]: Raw Sequence"); } return result; } } }