blob: 83095d2ed47c3d00dc7496710341206955210614 [file] [log] [blame]
/*
* 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.cassandra.fqltool.commands;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.AbstractIterator;
import io.airlift.airline.Arguments;
import io.airlift.airline.Command;
import io.airlift.airline.Option;
import net.openhft.chronicle.core.io.Closeable;
import net.openhft.chronicle.queue.ChronicleQueue;
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueueBuilder;
import net.openhft.chronicle.queue.ExcerptTailer;
import org.apache.cassandra.fqltool.FQLQueryIterator;
import org.apache.cassandra.fqltool.ResultHandler;
import org.apache.cassandra.fqltool.StoredResultSet;
/**
*/
@Command(name = "compare", description = "Compare result files generated by fqltool replay")
public class Compare implements Runnable
{
@Arguments(usage = "<path1> [<path2>...<pathN>]",
description = "Directories containing result files to compare.",
required = true)
private List<String> arguments = new ArrayList<>();
@Option(title = "queries",
name = { "--queries"},
description = "Directory to read the queries from. It is produced by the fqltool replay --store-queries option. ",
required = true)
private String querylog;
@Override
public void run()
{
compare(querylog, arguments);
}
public static void compare(String querylog, List<String> arguments)
{
List<ChronicleQueue> readQueues = null;
try (ResultHandler rh = new ResultHandler(arguments, null, null);
ChronicleQueue queryQ = SingleChronicleQueueBuilder.single(querylog).readOnly(true).build();
FQLQueryIterator queries = new FQLQueryIterator(queryQ.createTailer(), 1))
{
readQueues = arguments.stream().map(s -> SingleChronicleQueueBuilder.single(s).readOnly(true).build()).collect(Collectors.toList());
List<Iterator<ResultHandler.ComparableResultSet>> its = readQueues.stream().map(q -> new StoredResultSetIterator(q.createTailer())).collect(Collectors.toList());
while (queries.hasNext())
rh.handleResults(queries.next(), resultSets(its));
}
catch (Exception e)
{
throw new RuntimeException(e);
}
finally
{
if (readQueues != null)
readQueues.forEach(Closeable::close);
}
}
@VisibleForTesting
public static List<ResultHandler.ComparableResultSet> resultSets(List<Iterator<ResultHandler.ComparableResultSet>> its)
{
List<ResultHandler.ComparableResultSet> resultSets = new ArrayList<>(its.size());
for (Iterator<ResultHandler.ComparableResultSet> it : its)
{
if (it.hasNext())
resultSets.add(it.next());
else
resultSets.add(null);
}
return resultSets;
}
@VisibleForTesting
public static class StoredResultSetIterator extends AbstractIterator<ResultHandler.ComparableResultSet>
{
private final ExcerptTailer tailer;
public StoredResultSetIterator(ExcerptTailer tailer)
{
this.tailer = tailer;
}
protected ResultHandler.ComparableResultSet computeNext()
{
StoredResultSet srs = StoredResultSet.fromTailer(tailer);
if (srs.hasMoreResultSets)
return srs;
return endOfData();
}
}
}