/* * Copyright (C) 2014 Indeed Inc. * * 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.indeed.imhotep.client; import com.indeed.imhotep.api.FTGSIterator; import com.indeed.imhotep.api.ImhotepOutOfMemoryException; import com.indeed.imhotep.api.ImhotepSession; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.PriorityQueue; import java.util.Scanner; import java.util.StringTokenizer; /** * @author jsgroth */ public class InteractiveShell { public static void main(String[] args) throws ImhotepOutOfMemoryException, IOException { final HostsReloader reloader; if (args[0].equals("--hostsfile")) { reloader = new FileHostsReloader(args[1]); } else if (args[0].equals("--zknodes")) { reloader = new ZkHostsReloader(args[1], true); } else { throw new RuntimeException(); } main(reloader); } public static void main(final HostsReloader reloader) throws ImhotepOutOfMemoryException, IOException { final ImhotepClient client = new ImhotepClient(reloader); final Scanner sc = new Scanner(System.in); ImhotepSession activeSession = null; int numStats = 0; try { while (true) { System.out.print("> "); final String input = sc.nextLine(); if (input.startsWith("open")) { final StringTokenizer tokenizer = new StringTokenizer(input); tokenizer.nextToken(); // open final String dataset = tokenizer.nextToken(); final List<String> requestedShards = new ArrayList<String>(); while (tokenizer.hasMoreTokens()) { requestedShards.add(tokenizer.nextToken()); } activeSession = client.sessionBuilder(dataset, null, null).shardsOverride(requestedShards).build(); } else if (input.equals("close")) { if (activeSession != null) activeSession.close(); activeSession = null; } else if (input.startsWith("push")) { final String metric = input.split(" ", 2)[1]; if (activeSession != null) numStats = activeSession.pushStat(metric); } else if (input.equals("pop")) { if (activeSession != null) numStats = activeSession.popStat(); } else if (input.startsWith("top")) { final StringTokenizer tokenizer = new StringTokenizer(input); tokenizer.nextToken(); // top final int k = Integer.parseInt(tokenizer.nextToken()); String[] intFields = null; String[] stringFields = null; while (tokenizer.hasMoreTokens()) { final String token = tokenizer.nextToken(); if (token.startsWith("if=")) { intFields = token.substring("if=".length()).split(","); } else if (token.startsWith("sf=")) { stringFields = token.substring("sf=".length()).split(","); } } if (intFields == null) intFields = new String[0]; if (stringFields == null) stringFields = new String[0]; final FTGSIterator iterator = activeSession.getFTGSIterator(intFields, stringFields); final List<TGSTuple>[] topk = collectTopK(iterator, k, numStats); for (int i = 0; i < numStats; ++i) { System.out.println("stat "+i+":"); for (final TGSTuple t : topk[i]) { System.out.println(t); } } } else if (input.equals("quit")) { break; } } } finally { if (activeSession != null) activeSession.close(); client.close(); } } @SuppressWarnings("unchecked") public static List<TGSTuple>[] collectTopK(final FTGSIterator iterator, final int k, final int numStats) { final long[] statAccumBuf = new long[numStats]; final long[] statBuf = new long[numStats]; final PriorityQueue<TGSTuple>[] pqs = new PriorityQueue[numStats]; for (int i = 0; i < pqs.length; ++i) { pqs[i] = new PriorityQueue<TGSTuple>(k+1); } while (iterator.nextField()) { final String fieldName = iterator.fieldName(); final boolean fieldIsIntType = iterator.fieldIsIntType(); while (iterator.nextTerm()) { final long termIntVal = fieldIsIntType ? iterator.termIntVal() : 0; final String termStringVal = fieldIsIntType ? null : iterator.termStringVal(); Arrays.fill(statAccumBuf, 0L); while (iterator.nextGroup()) { iterator.groupStats(statBuf); for (int i = 0; i < numStats; ++i) { statAccumBuf[i] += statBuf[i]; } } for (int i = 0; i < numStats; ++i) { final PriorityQueue<TGSTuple> pq = pqs[i]; pq.add(new TGSTuple(fieldName, fieldIsIntType, termIntVal, termStringVal, statAccumBuf[i])); while (pq.size() > k) pq.remove(); } } } final List<TGSTuple>[] ret = new List[numStats]; for (int i = 0; i < numStats; ++i) { ret[i] = new ArrayList<TGSTuple>(pqs[i]); Collections.sort(ret[i]); Collections.reverse(ret[i]); } return ret; } public static class TGSTuple implements Comparable<TGSTuple> { public final String field; public final boolean fieldIsIntType; public final long termIntVal; public final String termStringVal; public final long stat; public TGSTuple(String field, boolean fieldIsIntType, long termIntVal, String termStringVal, long stat) { this.field = field; this.fieldIsIntType = fieldIsIntType; this.termIntVal = termIntVal; this.termStringVal = termStringVal; this.stat = stat; } @Override public int compareTo(TGSTuple o) { return (int)(stat - o.stat); } @Override public String toString() { return field+":"+(fieldIsIntType ? termIntVal : termStringVal)+" - "+stat; } } }