/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * 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 com.linkedin.pinot.tools.perf; import com.google.common.base.Preconditions; import com.linkedin.pinot.core.segment.index.SegmentMetadataImpl; import com.linkedin.pinot.tools.AbstractBaseCommand; import com.linkedin.pinot.tools.Command; import java.io.File; import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.kohsuke.args4j.CmdLineParser; import org.kohsuke.args4j.Option; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @SuppressWarnings("FieldCanBeLocal") public class PerfBenchmarkRunner extends AbstractBaseCommand implements Command { private static final Logger LOGGER = LoggerFactory.getLogger(PerfBenchmarkRunner.class); @Option(name = "-mode", required = true, metaVar = "<String>", usage = "Mode of the PerfBenchmarkRunner (startAll|startAllButServer|startServerWithPreLoadedSegments).") private String _mode; @Option(name = "-dataDir", required = false, metaVar = "<String>", usage = "Path to data directory.") private String _dataDir; @Option(name = "-tempDir", required = false, metaVar = "<String>", usage = "Path to temporary directory to start the cluster") private String _tempDir = "/tmp/"; @Option(name = "-loadMode", required = false, metaVar = "<String>", usage = "Load mode of the segments (HEAP|MMAP).") private String _loadMode = "HEAP"; @Option(name = "-segmentFormatVersion", required = false, metaVar = "<String>", usage = "Segment format version to be loaded (v1|v3).") private String _segmentFormatVersion = "v1"; @Option(name = "-batchLoad", required = false, metaVar = "<boolean>", usage = "Batch load multiple tables.") private boolean _isBatchLoad; @Option(name = "-numThreads", required = false, metaVar = "<int>", usage = "Number of threads for batch load (default 10).") private int _numThreads = 10; @Option(name = "-timeoutInSeconds", required = false, metaVar = "<int>", usage = "Timeout in seconds for batch load (default 60).") private int _timeoutInSeconds = 60; @Option(name = "-tableNames", required = false, metaVar = "<String>", usage = "Comma separated table names to be loaded (non-batch load).") private String _tableNames; @Option(name = "-invertedIndexColumns", required = false, metaVar = "<String>", usage = "Comma separated inverted index columns to be created (non-batch load).") private String _invertedIndexColumns; @Option(name = "-help", required = false, help = true, aliases = {"-h", "--h", "--help"}, usage = "Print this message.") private boolean _help = false; @Override public boolean getHelp() { return _help; } @Override public String getName() { return getClass().getSimpleName(); } @Override public String description() { return "Start Pinot cluster with optional preloaded segments."; } @Override public boolean execute() throws Exception { if (_mode.equalsIgnoreCase("startAll") || _mode.equalsIgnoreCase("startAllButServer")) { startAllButServer(); } if (_mode.equalsIgnoreCase("startAll") || _mode.equalsIgnoreCase("startServerWithPreLoadedSegments")) { startServerWithPreLoadedSegments(); } return true; } public void startAllButServer() throws Exception { PerfBenchmarkDriverConf perfBenchmarkDriverConf = new PerfBenchmarkDriverConf(); perfBenchmarkDriverConf.setStartServer(false); PerfBenchmarkDriver driver = new PerfBenchmarkDriver(perfBenchmarkDriverConf, _tempDir, _loadMode, _segmentFormatVersion, false); driver.run(); } private void startServerWithPreLoadedSegments() throws Exception { PerfBenchmarkDriverConf perfBenchmarkDriverConf = new PerfBenchmarkDriverConf(); perfBenchmarkDriverConf.setStartZookeeper(false); perfBenchmarkDriverConf.setStartController(false); perfBenchmarkDriverConf.setStartBroker(false); perfBenchmarkDriverConf.setServerInstanceDataDir(_dataDir); final PerfBenchmarkDriver driver = new PerfBenchmarkDriver(perfBenchmarkDriverConf, _tempDir, _loadMode, _segmentFormatVersion, false); driver.run(); if (_isBatchLoad) { String[] tableNames = new File(_dataDir).list(); Preconditions.checkNotNull(tableNames); ExecutorService executorService = Executors.newFixedThreadPool(_numThreads); for (final String tableName : tableNames) { executorService.submit(new Runnable() { @Override public void run() { try { loadTable(driver, _dataDir, tableName, null); } catch (Exception e) { LOGGER.error("Caught exception while loading table: {}", tableName, e); } } }); } executorService.shutdown(); executorService.awaitTermination(_timeoutInSeconds, TimeUnit.SECONDS); } else { List<String> invertedIndexColumns = null; if (_invertedIndexColumns != null) { invertedIndexColumns = Arrays.asList(_invertedIndexColumns.split(",")); } for (String tableName : _tableNames.split(",")) { loadTable(driver, _dataDir, tableName, invertedIndexColumns); } } } public static void loadTable(PerfBenchmarkDriver driver, String dataDir, String tableName, List<String> invertedIndexColumns) throws Exception { boolean tableConfigured = false; File[] segments = new File(dataDir, tableName).listFiles(); Preconditions.checkNotNull(segments); for (File segment : segments) { SegmentMetadataImpl segmentMetadata = new SegmentMetadataImpl(segment); if (!tableConfigured) { driver.configureTable(segmentMetadata.getTableName(), invertedIndexColumns); tableConfigured = true; } driver.addSegment(segmentMetadata); } } /** * Main method for the class. * * @param args arguments for the perf benchmark runner. * @throws Exception */ public static void main(String[] args) throws Exception { PerfBenchmarkRunner perfBenchmarkRunner = new PerfBenchmarkRunner(); CmdLineParser parser = new CmdLineParser(perfBenchmarkRunner); parser.parseArgument(args); if (perfBenchmarkRunner._help) { perfBenchmarkRunner.printUsage(); } else { perfBenchmarkRunner.execute(); } } }