/* * Copyright 2013 Eediom 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 org.araqne.logdb.client; import java.io.BufferedReader; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.PatternLayout; import org.araqne.logdb.client.http.WebSocketTransport; import au.com.bytecode.opencsv.CSVWriter; /** * 커맨드라인을 통해 로그프레소 서버에 접속하여 명령을 실행할 수 있도록 지원합니다. * * @author xeraph@eediom.com * */ public class Console { private BufferedReader br; private LogDbClient client; private String host; private String loginName; private String password; /** * 콘솔 클라이언트 진입점 */ public static void main(String[] args) throws IOException { ConsoleAppender ca = new ConsoleAppender(new PatternLayout()); ca.setThreshold(Level.INFO); org.apache.log4j.BasicConfigurator.configure(ca); Map<String, String> opts = getOpts(args); if (opts.containsKey("-e")) { oneShotQuery(opts); return; } new Console().run(); } private static void oneShotQuery(Map<String, String> opts) throws IOException { CSVWriter csvWriter = null; try { LogDbClient client = null; try { String query = null; String queryPath = opts.get("-f"); if (queryPath != null) { File f = new File(queryPath); if (!f.exists()) { System.err.println("query file not found: " + f.getAbsolutePath()); System.exit(-1); } if (!f.canRead()) { System.err.println("check query file permission: " + f.getAbsolutePath()); System.exit(-1); } query = readQueryFile(f); } if (query == null) query = getOpt(opts, "-e", "Error: -e, query string is missing"); String host = getOpt(opts, "-h", "Error: -h, host is required"); String loginName = getOpt(opts, "-u", "Error: -u, login name is required"); String password = getOpt(opts, "-p", "Error: -p, password is required"); String port = getOpt(opts, "-P", "Error: -P, port is required"); String cols = opts.get("-c"); String useSsl = opts.get("-s"); String skipCertCheck = opts.get("-S"); String[] headers = null; String[] line = null; if (cols != null && !cols.trim().isEmpty()) { headers = cols.split(","); for (int i = 0; i < headers.length; i++) headers[i] = headers[i].trim(); line = new String[headers.length]; } if(useSsl != null) { if(skipCertCheck != null) client = new LogDbClient(new WebSocketTransport(true, true)); else client = new LogDbClient(new WebSocketTransport(true)); } else { if(skipCertCheck != null) throw new IllegalArgumentException("Error: -S, must be used with -s(SSL) option"); else client = new LogDbClient(); } client.connect(host, Integer.valueOf(port), loginName, password); String lineEnd = System.getProperty("line.separator"); csvWriter = new CSVWriter(new OutputStreamWriter(System.out), CSVWriter.DEFAULT_SEPARATOR, CSVWriter.DEFAULT_QUOTE_CHARACTER, lineEnd); LogCursor cursor = client.query(query); while (cursor.hasNext()) { Map<String, Object> m = cursor.next(); if (line == null) System.out.println(m); else { for (int i = 0; i < line.length; i++) { Object o = m.get(headers[i]); line[i] = o == null ? "" : o.toString(); } csvWriter.writeNext(line); } } } finally { ensureClose(csvWriter); ensureClose(client); } } catch (IllegalArgumentException e) { e.printStackTrace(); System.err.println(e.getMessage()); System.exit(-1); } } private static String readQueryFile(File f) { BufferedReader br = null; FileInputStream is = null; StringBuilder sb = new StringBuilder(); try { is = new FileInputStream(f); br = new BufferedReader(new InputStreamReader(is, "utf-8")); while (true) { String line = br.readLine(); if (line == null) break; if (!line.trim().startsWith("#")) sb.append(" " + line); } } catch (IOException e) { System.err.println(e.getMessage()); System.exit(-1); } finally { ensureClose(is); } return sb.toString(); } private static void ensureClose(Closeable c) { if (c != null) { try { c.close(); } catch (IOException e) { } } } private static String getOpt(Map<String, String> opts, String key, String msg) { String val = opts.get(key); if (val == null) throw new IllegalArgumentException(msg); return val; } private static Map<String, String> getOpts(String[] args) { String name = null; String value = ""; Map<String, String> opts = new HashMap<String, String>(); for (String arg : args) { if (arg.startsWith("-")) { if (name != null) { opts.put(name, value); value = ""; } name = arg; } else { value = arg; } } if (name != null) opts.put(name, value); return opts; } /** * 콘솔 명령 루프를 실행합니다. */ public void run() throws IOException { w("Araqne LogDB Console 0.9.5 (2014-05-15)"); w("Type \"help\" for more information"); br = new BufferedReader(new InputStreamReader(System.in)); try { while (true) { System.out.print(getPrompt()); String line = br.readLine(); if (line == null) break; if (line.trim().isEmpty()) continue; String[] tokens = tokenize(line); if (tokens.length == 0) continue; String cmd = tokens[0].trim(); if (cmd.equals("quit") || cmd.equals("exit")) break; else if (cmd.equals("help")) help(); else if (cmd.equals("connect")) connect(tokens); else if (cmd.equals("disconnect")) disconnect(); else if (cmd.equals("query")) query(tokens); else if (cmd.equals("create_query")) createQuery(tokens); else if (cmd.equals("start_query")) startQuery(tokens); else if (cmd.equals("stop_query")) stopQuery(tokens); else if (cmd.equals("remove_query")) removeQuery(tokens); else if (cmd.equals("fetch")) fetch(tokens); else if (cmd.equals("queries")) queries(); else if (cmd.equals("query_status")) queryStatus(tokens); else if (cmd.equals("create_table")) createTable(tokens); else if (cmd.equals("drop_table")) dropTable(tokens); else if (cmd.equals("tables")) listTables(); else if (cmd.equals("table")) manageTable(tokens); else if (cmd.equals("loggers")) listLoggers(); else if (cmd.equals("logger_factories")) listLoggerFactories(); else if (cmd.equals("parser_factories")) listParserFactories(); else if (cmd.equals("parser_factory")) getParserFactoryInfo(tokens); else if (cmd.equals("parsers")) listParsers(); else if (cmd.equals("transformer_factories")) listTransformerFactories(); else if (cmd.equals("transformer_factory")) getTransformerFactoryInfo(tokens); else if (cmd.equals("transformers")) listTransformers(); else if (cmd.equals("create_transformer")) createTransformer(tokens); else if (cmd.equals("remove_transformer")) removeTransformer(tokens); else if (cmd.equals("create_parser")) createParser(tokens); else if (cmd.equals("remove_parser")) removeParser(tokens); else if (cmd.equals("test_parse")) testParse(tokens); else if (cmd.equals("create_logger")) createLogger(tokens); else if (cmd.equals("remove_logger")) removeLogger(tokens); else if (cmd.equals("start_logger")) startLogger(tokens); else if (cmd.equals("stop_logger")) stopLogger(tokens); else if (cmd.equals("index_tokenizers")) listIndexTokenizers(tokens); else if (cmd.equals("indexes")) listIndexes(tokens); else if (cmd.equals("index")) getIndexInfo(tokens); else if (cmd.equals("create_index")) createIndex(tokens); else if (cmd.equals("drop_index")) dropIndex(tokens); else if (cmd.equals("test_index_tokenize")) testIndexTokenize(tokens); else if (cmd.equals("accounts")) listAccounts(tokens); else if (cmd.equals("create_account")) createAccount(tokens); else if (cmd.equals("remove_account")) removeAccount(tokens); else if (cmd.equals("passwd")) changePassword(tokens); else if (cmd.equals("grant")) grantPrivilege(tokens); else if (cmd.equals("revoke")) revokePrivilege(tokens); else if (cmd.equals("archives")) listArchiveConfigs(tokens); else if (cmd.equals("create_archive")) createArchiveConfig(tokens); else if (cmd.equals("remove_archive")) removeArchiveConfig(tokens); else if (cmd.equals("engines")) engines(); else w("syntax error"); } } finally { if (client != null) { w("closing logdb connection..."); client.close(); w("bye!"); } } } private void connect(String[] tokens) { if (tokens.length < 3) { w("Usage: connect <host:port> <loginname> [<password>]"); return; } if (client != null) { w("already connected"); return; } String addr = tokens[1]; String[] addrTokens = addr.split(":"); host = addrTokens[0]; int port = 80; if (addrTokens.length > 1) port = Integer.valueOf(addrTokens[1]); try { InetAddress.getByName(host); } catch (UnknownHostException e) { w("invalid hostname " + host + ", connect failed"); return; } loginName = tokens[2]; password = ""; if (tokens.length > 3) password = tokens[3]; try { client = new LogDbClient(); client.connect(host, port, loginName, password); w("connected to " + host + " as " + loginName); } catch (Throwable t) { w(t.getMessage()); if (client != null) { try { client.close(); } catch (IOException e) { } client = null; } } } private void disconnect() { if (client == null) { w("not connected yet"); return; } w("closing connection..."); try { client.close(); } catch (IOException e) { } w("disconnected"); client = null; } private void queries() { if (client == null) { w("connect first please"); return; } try { List<LogQuery> queries = client.getQueries(); if (queries.size() == 0) { w("no result"); return; } for (LogQuery query : queries) { w(query.toString()); } } catch (Throwable t) { w(t.getMessage()); } } private void queryStatus(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: query_status <query_id>"); return; } try { LogQuery query = client.getQuery(Integer.valueOf(tokens[1])); if (query == null) { w("query not found"); return; } w(query.toString()); for (LogQueryCommand cmd : query.getCommands()) w("\t" + cmd); } catch (Throwable t) { w(t.getMessage()); } } private void query(String[] tokens) { if (client == null) { w("connect first please"); return; } long begin = System.currentTimeMillis(); String queryString = join(tokens); w("querying [" + queryString + "] ..."); long count = 0; LogCursor cursor = null; try { cursor = client.query(queryString); while (cursor.hasNext()) { Object o = cursor.next(); w(o.toString()); count++; } long end = System.currentTimeMillis(); w("total " + count + " row(s), elapsed " + (end - begin) + "ms"); } catch (Throwable t) { if (client != null && client.isClosed()) client = null; w("query failed: " + t.getMessage()); } finally { if (cursor != null) { try { cursor.close(); } catch (IOException e) { } } } } private void createQuery(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: create_query <query_string>"); return; } try { String queryString = join(tokens); int id = client.createQuery(queryString); w("created query " + id); } catch (Throwable t) { w(t.getMessage()); } } private String join(String[] tokens) { StringBuilder sb = new StringBuilder(); int p = 0; for (int i = 1; i < tokens.length; i++) { String t = tokens[i]; if (p++ != 0) sb.append(" "); sb.append(t); } return sb.toString(); } private void startQuery(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: start_query <query_id>"); return; } try { int id = Integer.valueOf(tokens[1]); client.startQuery(id); w("started query " + id); } catch (Throwable t) { w(t.getMessage()); } } private void stopQuery(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: stop_query <query_id>"); return; } try { int id = Integer.valueOf(tokens[1]); client.stopQuery(id); w("stopped query " + id); } catch (Throwable t) { w(t.getMessage()); } } private void removeQuery(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: remove_query <query_id>"); return; } try { int id = Integer.valueOf(tokens[1]); client.removeQuery(id); w("removed query " + id); } catch (Throwable t) { w(t.getMessage()); } } @SuppressWarnings("unchecked") private void fetch(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 4) { w("Usage: fetch <query_id> <offset> <limit>"); return; } int id = Integer.valueOf(tokens[1]); long offset = Long.valueOf(tokens[2]); int limit = Integer.valueOf(tokens[3]); try { Map<String, Object> page = client.getResult(id, offset, limit); List<Object> rows = (List<Object>) page.get("result"); for (Object row : rows) w(row.toString()); w(rows.size() + " row(s)"); } catch (Throwable t) { w(t.getMessage()); } } private void createTable(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: create_table <table_name> <engine_type>"); return; } try { client.createTable(tokens[1], tokens[2]); w("created"); } catch (Throwable t) { w(t.getMessage()); } } private void dropTable(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: drop_table <table_name>"); return; } try { client.dropTable(tokens[1]); w("dropped"); } catch (Throwable t) { w(t.getMessage()); } } private void listTables() { if (client == null) { w("connect first please"); return; } try { for (TableSchemaInfo table : client.listTables()) { w("Table [" + table.getName() + "]"); for (Entry<String, String> e : table.getMetadata().entrySet()) w(" * " + e.getKey() + "=" + e.getValue()); } } catch (Throwable t) { w(t.getMessage()); } } private void manageTable(String[] tokens) throws IOException { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: table <table_name> [<key>] [<value>]"); return; } try { String tableName = tokens[1]; if (tokens.length == 2) { TableSchemaInfo table = client.getTableInfo(tableName); w("Table [" + table.getName() + "]"); w(""); // old version don't return primary storage config if (table.getPrimaryStorage() != null) { w("Primary Storage: type " + table.getPrimaryStorage().getType()); w("------------------------------"); if (table.getPrimaryStorage().getBasePath() != null) w("Base Path: " + table.getPrimaryStorage().getBasePath()); for (TableConfig config : table.getPrimaryStorage().getConfigs()) { w(config.toString()); } } if (table.getReplicaStorage() != null) { w(""); w("Replica Storage: type " + table.getReplicaStorage().getType()); w("------------------------------"); if (table.getReplicaStorage().getBasePath() != null) w("Base Path: " + table.getReplicaStorage().getBasePath()); for (TableConfig config : table.getReplicaStorage().getConfigs()) { w(config.toString()); } } if (!table.getMetadata().isEmpty()) { w(""); w("Metadata"); w("----------"); for (Entry<String, String> e : table.getMetadata().entrySet()) w(" * " + e.getKey() + "=" + e.getValue()); } } else { String key = tokens[2]; if (tokens.length == 3) { Set<String> keys = new HashSet<String>(); keys.add(key); client.unsetTableMetadata(tableName, keys); w("unset"); } else if (tokens.length == 4) { Map<String, String> config = new HashMap<String, String>(); String value = tokens[3]; config.put(key, value); client.setTableMetadata(tableName, config); w("set"); } } } catch (Throwable t) { w(t.getMessage()); } } private void listLoggers() { if (client == null) { w("connect first please"); return; } try { w("Loggers"); w("---------"); for (LoggerInfo logger : client.listLoggers()) w(logger.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void listLoggerFactories() { if (client == null) { w("connect first please"); return; } try { w("Logger Factories"); w("------------------"); for (LoggerFactoryInfo f : client.listLoggerFactories()) w(f.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void listParserFactories() { if (client == null) { w("connect first please"); return; } try { w("Parser Factories"); w("------------------"); for (ParserFactoryInfo f : client.listParserFactories()) w(f.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void getParserFactoryInfo(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: parser_factory <factory name>"); return; } try { w("Parser Factory"); w("------------------"); ParserFactoryInfo f = client.getParserFactoryInfo(tokens[1]); w(f.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void listParsers() { if (client == null) { w("connect first please"); return; } try { List<ParserInfo> parsers = client.listParsers(); if (parsers.size() == 0) { w("no result"); return; } w("Parsers"); w("----------"); for (ParserInfo parser : parsers) w(parser.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void createParser(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: create_parser <factory_name> <name>"); return; } try { ParserFactoryInfo f = client.getParserFactoryInfo(tokens[1]); ParserInfo p = new ParserInfo(); p.setFactoryName(tokens[1]); p.setName(tokens[2]); for (ConfigSpec type : f.getConfigSpecs()) { inputOption(p, type); } client.createParser(p); w("created"); } catch (Throwable t) { w(t.getMessage()); } } private void inputOption(ParserInfo parser, ConfigSpec spec) throws IOException { String directive = spec.isRequired() ? "(required)" : "(optional)"; System.out.print(spec.getDisplayName() + " " + directive + "? "); String value = br.readLine(); if (!value.isEmpty()) parser.getConfigs().put(spec.getName(), value); if (value.isEmpty() && spec.isRequired()) { inputOption(parser, spec); } } private void removeParser(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: remove_parser <name>"); return; } try { client.removeParser(tokens[1]); w("removed"); } catch (Throwable t) { w(t.getMessage()); } } private void testParse(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: test_parse <parser name> <line>"); return; } try { String name = tokens[1]; String line = tokens[2]; Map<String, Object> data = new HashMap<String, Object>(); data.put("line", line); List<Map<String, Object>> rows = client.testParser(name, data); w("Parsed rows"); w("-------------"); for (Map<String, Object> row : rows) { w(row.toString()); } } catch (Throwable t) { w(t.getMessage()); } } private void listTransformerFactories() { if (client == null) { w("connect first please"); return; } try { w("Transformer Factories"); w("------------------"); for (TransformerFactoryInfo f : client.listTransformerFactories()) w(f.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void getTransformerFactoryInfo(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: transformer_factory <factory name>"); return; } try { w("Transformer Factory"); w("------------------"); TransformerFactoryInfo f = client.getTransformerFactoryInfo(tokens[1]); w(f.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void listTransformers() { if (client == null) { w("connect first please"); return; } try { List<TransformerInfo> transformers = client.listTransformers(); if (transformers.size() == 0) { w("no result"); return; } w("Transformers"); w("--------------"); for (TransformerInfo transformer : transformers) w(transformer.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void createTransformer(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: create_transformer <factory_name> <name>"); return; } try { TransformerFactoryInfo f = client.getTransformerFactoryInfo(tokens[1]); TransformerInfo p = new TransformerInfo(); p.setFactoryName(tokens[1]); p.setName(tokens[2]); for (ConfigSpec type : f.getConfigSpecs()) { inputOption(p, type); } client.createTransformer(p); w("created"); } catch (Throwable t) { w(t.getMessage()); } } private void inputOption(TransformerInfo parser, ConfigSpec spec) throws IOException { String directive = spec.isRequired() ? "(required)" : "(optional)"; System.out.print(spec.getDisplayName() + " " + directive + "? "); String value = br.readLine(); if (!value.isEmpty()) parser.getConfigs().put(spec.getName(), value); if (value.isEmpty() && spec.isRequired()) { inputOption(parser, spec); } } private void removeTransformer(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: remove_transformer <name>"); return; } try { client.removeTransformer(tokens[1]); w("removed"); } catch (Throwable t) { w(t.getMessage()); } } private void createLogger(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 4) { w("Usage: create_logger <factory name> <namespace> <name>"); return; } try { LoggerInfo logger = new LoggerInfo(); logger.setFactoryName(tokens[1]); logger.setNamespace(tokens[2]); logger.setName(tokens[3]); LoggerFactoryInfo f = client.getLoggerFactoryInfo(tokens[1]); for (ConfigSpec type : f.getConfigSpecs()) { inputOption(logger, type); } client.createLogger(logger); w("created"); } catch (Throwable t) { w(t.getMessage()); } } private void inputOption(LoggerInfo logger, ConfigSpec spec) throws IOException { String directive = spec.isRequired() ? "(required)" : "(optional)"; System.out.print(spec.getDisplayName() + " " + directive + "? "); String value = br.readLine(); if (!value.isEmpty()) logger.getConfigs().put(spec.getName(), value); if (value.isEmpty() && spec.isRequired()) { inputOption(logger, spec); } } private void removeLogger(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: remove_logger <logger fullname>"); return; } try { client.removeLogger(tokens[1]); w("removed"); } catch (Throwable t) { w(t.getMessage()); } } private void startLogger(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: start_logger <logger fullname> <interval (millisec)>"); return; } try { client.startLogger(tokens[1], Integer.valueOf(tokens[2])); w("started with interval " + tokens[2] + "ms"); } catch (Throwable t) { w(t.getMessage()); } } private void listIndexTokenizers(String[] tokens) { if (client == null) { w("connect first please"); return; } try { for (IndexTokenizerFactoryInfo tokenizer : client.listIndexTokenizerFactories()) { w(tokenizer.toString()); } } catch (Throwable t) { w(t.getMessage()); } } private void listIndexes(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: indexes <table name>"); return; } try { for (IndexInfo index : client.listIndexes(tokens[1])) { w(index.toString()); } } catch (Throwable t) { w(t.getMessage()); } } private void getIndexInfo(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: index <table name> <index name>"); return; } try { IndexInfo index = client.getIndexInfo(tokens[1], tokens[2]); w(index.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void stopLogger(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: stop_logger <logger fullname>"); return; } try { client.stopLogger(tokens[1], 5000); w("stopped"); } catch (Throwable t) { w(t.getMessage()); } } private void createIndex(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: create_index <table name> <index name>"); return; } try { String tableName = tokens[1]; String indexName = tokens[2]; IndexInfo index = new IndexInfo(); index.setTableName(tableName); index.setIndexName(indexName); w("Available Index Tokenizers"); w("----------------------------"); List<IndexTokenizerFactoryInfo> tokenizers = client.listIndexTokenizerFactories(); for (IndexTokenizerFactoryInfo tokenizer : tokenizers) { w(tokenizer.toString()); } System.out.print("select tokenizer? "); String tokenizerName = br.readLine().trim(); IndexTokenizerFactoryInfo selected = null; for (IndexTokenizerFactoryInfo tokenizer : tokenizers) { if (tokenizer.getName().equals(tokenizerName)) selected = tokenizer; } if (selected == null) { w("invalid index tokenizer"); return; } index.setTokenizerName(tokenizerName); for (IndexConfigSpec type : selected.getConfigSpecs()) { inputOption(index, type); } System.out.print("use bloom filter (y/N)? "); index.setUseBloomFilter(br.readLine().trim().equalsIgnoreCase("y")); if (index.isUseBloomFilter()) { System.out.print("bloom filter lv0 capacity (enter to use default)? "); String t = br.readLine().trim(); if (!t.isEmpty()) index.setBloomFilterCapacity0(Integer.valueOf(t)); System.out.print("bloom filter lv0 error rate (0<x<1, enter to use default)? "); t = br.readLine().trim(); if (!t.isEmpty()) index.setBloomFilterErrorRate0(Double.valueOf(t)); System.out.print("bloom filter lv1 capacity (enter to use default)? "); if (!t.isEmpty()) index.setBloomFilterCapacity1(Integer.valueOf(t)); System.out.print("bloom filter lv1 error rate (0<x<1, enter to use default)? "); if (!t.isEmpty()) index.setBloomFilterErrorRate1(Double.valueOf(t)); } System.out.print("base path (optional)? "); String basePath = br.readLine().trim(); if (basePath.isEmpty()) basePath = null; index.setBasePath(basePath); System.out.print("build past index (y/n)? "); String s = br.readLine().trim(); index.setBuildPastIndex(s.equalsIgnoreCase("y")); if (index.isBuildPastIndex()) { System.out.print("min day (yyyymmdd or enter to skip)? "); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); String minDayStr = br.readLine().trim(); if (minDayStr != null) index.setMinIndexDay(dateFormat.parse(minDayStr)); } client.createIndex(index); w("created"); } catch (Throwable t) { w(t.getMessage()); } } private void inputOption(IndexInfo index, IndexConfigSpec spec) throws IOException { String directive = spec.isRequired() ? "(required)" : "(optional)"; System.out.print(spec.getName() + " " + directive + "? "); String value = br.readLine(); if (!value.isEmpty()) index.getTokenizerConfigs().put(spec.getKey(), value); if (value.isEmpty() && spec.isRequired()) { inputOption(index, spec); } } private void dropIndex(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: drop_index <table name> <index name>"); return; } try { client.dropIndex(tokens[1], tokens[2]); w("dropped"); } catch (Throwable t) { w(t.getMessage()); } } private void testIndexTokenize(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 4) { w("Usage: test_index_tokenize <table name> <index name> <line>"); return; } try { String tableName = tokens[1]; String indexName = tokens[2]; String line = tokens[3]; Map<String, Object> data = new HashMap<String, Object>(); data.put("line", line); Set<String> s = client.testIndexTokenizer(tableName, indexName, data); w("Fulltext Tokens"); w("-----------------"); for (String t : s) w(t); } catch (Throwable t) { w(t.getMessage()); } } private void listAccounts(String[] tokens) { if (client == null) { w("connect first please"); return; } try { for (AccountInfo account : client.listAccounts()) w(account.toString()); } catch (Throwable t) { w(t.getMessage()); } } private void createAccount(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: create_account <login name> <password>"); return; } try { AccountInfo account = new AccountInfo(); account.setLoginName(tokens[1]); account.setPassword(tokens[2]); client.createAccount(account); w("created"); } catch (Throwable t) { w(t.getMessage()); } } private void removeAccount(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: remove_account <login name>"); return; } try { client.removeAccount(tokens[1]); w("removed"); } catch (Throwable t) { w(t.getMessage()); } } private void changePassword(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: passwd <login name> <password>"); return; } try { client.changePassword(tokens[1], tokens[2]); w("changed"); } catch (Throwable t) { w(t.getMessage()); } } private void grantPrivilege(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: grant <login name> <table name>"); return; } try { client.grantPrivilege(new Privilege(tokens[1], tokens[2])); w("granted"); } catch (Throwable t) { w(t.getMessage()); } } private void revokePrivilege(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: revoke <login name> <table name>"); return; } try { client.revokePrivilege(new Privilege(tokens[1], tokens[2])); w("revoked"); } catch (Throwable t) { w(t.getMessage()); } } private void listArchiveConfigs(String[] tokens) { if (client == null) { w("connect first please"); return; } try { w("Archive Configs"); w("-----------------"); for (ArchiveConfig config : client.listArchiveConfigs()) { w(config.toString()); } } catch (Throwable t) { w(t.getMessage()); } } private void createArchiveConfig(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 3) { w("Usage: create_archive <logger fullname> <table name> [<host name>]"); return; } try { ArchiveConfig config = new ArchiveConfig(); config.setLoggerName(tokens[1]); config.setTableName(tokens[2]); if (tokens.length > 3) config.setHost(tokens[3]); config.setEnabled(true); client.createArchiveConfig(config); w("created"); } catch (Throwable t) { w(t.getMessage()); } } private void removeArchiveConfig(String[] tokens) { if (client == null) { w("connect first please"); return; } if (tokens.length < 2) { w("Usage: remove_archive <logger fullname>"); return; } try { client.removeArchiveConfig(tokens[1]); w("removed"); } catch (Throwable t) { w(t.getMessage()); } } private void engines() { if (client == null) { w("connect first please"); return; } try { List<StorageEngineInfo> engines = client.listStorageEngines(); for (StorageEngineInfo e : engines) w(e.toString()); } catch (Throwable t) { w(t.getMessage()); } } private String getPrompt() { if (client != null) return "logdb@" + host + "> "; return "logdb> "; } private void help() { w("connect <host> <loginname> <password>"); w("\tconnect to specified araqne logdb instance"); w("disconnect"); w("\tdisconnect database connection"); w("queries"); w("\tprint all queries initiated by this session"); w("query <query string>"); w("\tcreate, start and fetch query result at once"); w("create_query <query string>"); w("\tcreate query with specified query string, and return allocated query id"); w("start_query <query id>"); w("\tstart query"); w("stop_query <query_id>"); w("\tstop running query"); w("remove_query <query_id>"); w("\tstop and remove query"); w("fetch <query_id> <offset> <limit>"); w("\tfetch result set of specified window. you can fetch partial result before query is ended"); } private static void w(String s) { System.out.println(s); } private static String[] tokenize(String line) { StringBuilder sb = new StringBuilder(); List<String> args = new ArrayList<String>(); boolean quoteOpen = false; boolean squoteOpen = false; boolean escape = false; int i = 0; while (true) { if (i >= line.length()) break; char c = line.charAt(i); i++; if (c == '\\') { if (escape) { escape = false; sb.append(c); } else if (squoteOpen) { sb.append(c); } else { escape = true; } continue; } if (c == '"') { if (escape) { escape = false; sb.append(c); } else if (squoteOpen) { sb.append(c); } else { quoteOpen = !quoteOpen; if (!quoteOpen) { args.add(sb.toString()); sb = new StringBuilder(); } } continue; } if (c == '\'') { if (escape) { escape = false; sb.append(c); } else { quoteOpen = !quoteOpen; squoteOpen = !squoteOpen; if (!quoteOpen) { args.add(sb.toString()); sb = new StringBuilder(); } } continue; } if (c == ' ' && !(quoteOpen)) { String parsed = sb.toString(); if (!parsed.trim().isEmpty()) args.add(parsed); sb = new StringBuilder(); continue; } if (c != '\\' && escape) { sb.append('\\'); escape = false; } sb.append(c); } String parsed = sb.toString(); if (!parsed.trim().isEmpty()) args.add(sb.toString()); return args.toArray(new String[0]); } }