com.bigdata.bop.engine.SolutionsLog Maven / Gradle / Ivy
/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
[email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Created on Sep 29, 2011
*/
package com.bigdata.bop.engine;
import java.util.Iterator;
import java.util.UUID;
import org.apache.log4j.Logger;
import com.bigdata.bop.BOp;
import com.bigdata.bop.IBindingSet;
import com.bigdata.bop.IPredicate;
import com.bigdata.bop.IVariableOrConstant;
import com.bigdata.bop.join.PipelineJoin;
import com.bigdata.util.Bytes;
/**
* Class provides a logger which may be used for observing all solutions flowing
* into each operator in the query plan and the final solutions flowing into the
* query buffer.
*
* @author Bryan Thompson
* @version $Id$
*/
public class SolutionsLog {
/**
* Logging for this class should be performed when this logger has a detail
* level of at least INFO.
*/
public static final Logger solutionsLog = Logger.getLogger(SolutionsLog.class);
public static final boolean INFO = solutionsLog.isInfoEnabled();
/**
* A single buffer is reused to keep down the heap churn.
*/
final private static StringBuilder sb = new StringBuilder(
Bytes.kilobyte32 * 4);
private static boolean first = true;
static private void prefix(final UUID queryId, final BOp bop, final int bopId,
final int partitionId, final int chunkSize) {
if (first) {
// If first time, then write out the header.
solutionsLog.info("QueryUUID\tbop\tbopId\tpartitionId\tchunkSize\n");
first = false;
}
sb.setLength(0);
sb.append(queryId);
sb.append('\t');
sb.append(bop == null ? "N/A" : bop.getClass().getSimpleName());
// sb.append('\t');
// sb.append(getPredSummary(bop));
sb.append('\t');
sb.append(bopId);
sb.append('\t');
sb.append(partitionId);
sb.append('\t');
sb.append(chunkSize);
sb.append('\t');
}
/**
* If the bop is a join then return a summary of the predicate.
*
* @param bop
* The bop.
*
* @return The predicate summary iff the bop is a join.
*/
static private String getPredSummary(final BOp bop) {
final IPredicate> pred = (IPredicate>) bop
.getProperty(PipelineJoin.Annotations.PREDICATE);
if (pred == null)
return "";
final StringBuilder sb = new StringBuilder();
final Integer predId = pred == null ? null : (Integer) pred
.getProperty(BOp.Annotations.BOP_ID);
sb.append(pred.getClass().getSimpleName());
sb.append("[" + predId + "](");
final Iterator itr = pred.argIterator();
boolean first = true;
while (itr.hasNext()) {
if (first) {
first = false;
} else
sb.append(", ");
final IVariableOrConstant> x = (IVariableOrConstant>) itr
.next();
if (x.isVar()) {
sb.append("?");
sb.append(x.getName());
} else {
sb.append(x.get());
// sb.append(((IV)x.get()).getValue());
}
}
sb.append(")");
return sb.toString();
}
// /**
// *
// * TODO This can not be used because the {@link LocalChunkMessage} wraps an
// * iterator rather than an {@link IBindingSet}[]. Visiting the iterator on
// * that class therefore *drains* the chunk and it can not be "rewound". We
// * should entirely get rid of the {@link IAsynchronousIterator} in {@link
// * IChunkMessage}s. It was original developed to provide chunked
// * transmission of solutions between asynchronous processes, but that is now
// * handled by the {@link QueryEngine} and the {@link PipelineOp}s and the
// * {@link IChunkMessage} could both operate in terms of a simpler
// * abstraction. (It can not be as simple as a single embedded {@link
// * IBindingSet}[] because the data should not be fully materialized onto the
// * JVM heap for an {@link NIOChunkMessage}, but it could be an
// * IClosableIterator visiting either IBindingSets or IBindingSet chunks (if
// * two levels of chunking makes sense for an {@link NIOChunkMessage}, which
// * I doubt)).
// */
// synchronized static void log(final IChunkMessage msg) {
//
// prefix(msg.getQueryId(), msg.getBOpId(), msg.getPartitionId());
//
// final int headerLen = sb.length();
//
// final IAsynchronousIterator itr = msg.getChunkAccessor()
// .iterator();
//
// try {
//
// while (itr.hasNext()) {
//
// final IBindingSet[] a = itr.next();
//
// for (IBindingSet bset : a) {
//
// sb.append(bset.toString());
//
// sb.append('\n');
//
// solutionsLog.info(sb);
//
// sb.setLength(headerLen);
//
// }
//
// }
//
// } finally {
//
// itr.close();
//
// }
//
// }
public synchronized static void log(final UUID queryId, final BOp bop,
final int bopId, final int partitionId, final IBindingSet[] a) {
prefix(queryId, bop, bopId, partitionId, a.length);
final int headerLen = sb.length();
for (IBindingSet bset : a) {
if (bset == null)
sb.append("NA");
else
sb.append(bset.toString());
sb.append('\n');
solutionsLog.info(sb);
sb.setLength(headerLen);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy