/* * 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.http; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Set; import org.araqne.logdb.client.AccountInfo; import org.araqne.logdb.client.ArchiveConfig; import org.araqne.logdb.client.ConfigSpec; import org.araqne.logdb.client.IndexConfigSpec; import org.araqne.logdb.client.IndexInfo; import org.araqne.logdb.client.IndexTokenizerFactoryInfo; import org.araqne.logdb.client.LogCursor; import org.araqne.logdb.client.LogQuery; import org.araqne.logdb.client.LoggerFactoryInfo; import org.araqne.logdb.client.LoggerInfo; import org.araqne.logdb.client.Message; import org.araqne.logdb.client.MessageException; import org.araqne.logdb.client.ParserFactoryInfo; import org.araqne.logdb.client.Privilege; import org.araqne.logdb.client.TableSchemaInfo; import org.araqne.logdb.client.http.impl.CometSession; import org.araqne.logdb.client.http.impl.TrapListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * HTTP 롱 폴링 기술을 이용한 코멧 클라이언트를 구현합니다. * * @author xeraph@eediom.com * @deprecated */ public class CometClient implements TrapListener { private final Logger logger = LoggerFactory.getLogger(CometClient.class); private CometSession session; private Map<Integer, LogQuery> queries = new HashMap<Integer, LogQuery>(); public List<LogQuery> getQueries() { return new ArrayList<LogQuery>(queries.values()); } public LogQuery getQuery(int id) { return queries.get(id); } public void connect(String host, String loginName, String password) throws IOException { connect(host, 80, loginName, password); } public void connect(String host, int port, String loginName, String password) throws IOException { this.session = new CometSession(host, port); this.session.login(loginName, password, true); this.session.addListener(this); } @SuppressWarnings("unchecked") public List<ArchiveConfig> listArchiveConfigs() throws IOException { List<ArchiveConfig> configs = new ArrayList<ArchiveConfig>(); Message resp = session.rpc("com.logpresso.core.msgbus.ArchivePlugin.getConfigs"); List<Map<String, Object>> l = (List<Map<String, Object>>) resp.get("configs"); for (Map<String, Object> m : l) { configs.add(parseArchiveConfig(m)); } return configs; } @SuppressWarnings("unchecked") public ArchiveConfig getArchiveConfig(String loggerName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("logger", loggerName); Message resp = session.rpc("com.logpresso.core.msgbus.ArchivePlugin.getConfig", params); Map<String, Object> m = (Map<String, Object>) resp.getParameters().get("config"); return parseArchiveConfig(m); } @SuppressWarnings("unchecked") private ArchiveConfig parseArchiveConfig(Map<String, Object> m) { ArchiveConfig c = new ArchiveConfig(); c.setLoggerName((String) m.get("logger")); c.setTableName((String) m.get("table")); c.setHost((String) m.get("host")); c.setEnabled((Boolean) m.get("enabled")); c.setMetadata((Map<String, String>) m.get("metadata")); return c; } public void createArchiveConfig(ArchiveConfig config) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("logger", config.getLoggerName()); params.put("table", config.getTableName()); params.put("host", config.getHost()); params.put("enabled", config.isEnabled()); params.put("metadata", config.getMetadata()); session.rpc("com.logpresso.core.msgbus.ArchivePlugin.createConfig", params); } public void removeArchiveConfig(String loggerName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("logger", loggerName); session.rpc("com.logpresso.core.msgbus.ArchivePlugin.removeConfig", params); } @SuppressWarnings("unchecked") public List<AccountInfo> listAccounts() throws IOException { Message resp = session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.listAccounts"); List<AccountInfo> accounts = new ArrayList<AccountInfo>(); List<Object> l = (List<Object>) resp.get("accounts"); for (Object o : l) { Map<String, Object> m = (Map<String, Object>) o; List<Object> pl = (List<Object>) m.get("privileges"); AccountInfo account = new AccountInfo(); String loginName = (String) m.get("login_name"); account.setLoginName(loginName); for (Object o2 : pl) { Map<String, Object> m2 = (Map<String, Object>) o2; String tableName = (String) m2.get("table_name"); Privilege p = new Privilege(loginName, tableName); account.getPrivileges().add(p); } accounts.add(account); } return accounts; } public void createAccount(AccountInfo account) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("login_name", account.getLoginName()); params.put("password", account.getPassword()); session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.createAccount", params); } public void removeAccount(String loginName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("login_name", loginName); session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.removeAccount", params); } public void changePassword(String loginName, String password) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("login_name", loginName); params.put("password", password); session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.changePassword", params); } public void grantPrivilege(Privilege privilege) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("login_name", privilege.getLoginName()); params.put("table_name", privilege.getTableName()); session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.grantPrivilege", params); } public void revokePrivilege(Privilege privilege) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("login_name", privilege.getLoginName()); params.put("table_name", privilege.getTableName()); session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.revokePrivilege", params); } @SuppressWarnings("unchecked") public List<IndexTokenizerFactoryInfo> listIndexTokenizerFactories() throws IOException { Message resp = session.rpc("com.logpresso.index.msgbus.ManagementPlugin.listIndexTokenizerFactories"); List<IndexTokenizerFactoryInfo> l = new ArrayList<IndexTokenizerFactoryInfo>(); for (Object o : (List<Object>) resp.getParameters().get("factories")) { IndexTokenizerFactoryInfo f = parseIndexTokenizerFactory(o); l.add(f); } return l; } public IndexTokenizerFactoryInfo getIndexTokenizerFactory(String name) throws IOException { Message resp = session.rpc("com.logpresso.index.msgbus.ManagementPlugin.getIndexTokenizerFactory"); return parseIndexTokenizerFactory(resp.getParameters().get("factory")); } @SuppressWarnings("unchecked") private IndexTokenizerFactoryInfo parseIndexTokenizerFactory(Object o) { Map<String, Object> m = (Map<String, Object>) o; IndexTokenizerFactoryInfo f = new IndexTokenizerFactoryInfo(); f.setName((String) m.get("name")); f.setConfigSpecs(parseIndexConfigList((List<Object>) m.get("config_specs"))); return f; } @SuppressWarnings("unchecked") private List<IndexConfigSpec> parseIndexConfigList(List<Object> l) { List<IndexConfigSpec> specs = new ArrayList<IndexConfigSpec>(); for (Object o : l) { Map<String, Object> m = (Map<String, Object>) o; IndexConfigSpec spec = new IndexConfigSpec(); spec.setKey((String) m.get("key")); spec.setName((String) m.get("name")); spec.setDescription((String) m.get("description")); spec.setRequired((Boolean) m.get("required")); specs.add(spec); } return specs; } @SuppressWarnings("unchecked") public List<IndexInfo> listIndexes(String tableName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); Message resp = session.rpc("com.logpresso.index.msgbus.ManagementPlugin.listIndexes", params); List<IndexInfo> indexes = new ArrayList<IndexInfo>(); List<Object> l = (List<Object>) resp.getParameters().get("indexes"); for (Object o : l) { Map<String, Object> m = (Map<String, Object>) o; IndexInfo indexInfo = getIndexInfo(m); indexes.add(indexInfo); } return indexes; } @SuppressWarnings("unchecked") public IndexInfo getIndexInfo(String tableName, String indexName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); params.put("index", indexName); Message resp = session.rpc("com.logpresso.index.msgbus.ManagementPlugin.getIndexInfo", params); return getIndexInfo((Map<String, Object>) resp.getParameters().get("index")); } @SuppressWarnings("unchecked") private IndexInfo getIndexInfo(Map<String, Object> m) { IndexInfo index = new IndexInfo(); index.setTableName((String) m.get("table")); index.setIndexName((String) m.get("index")); index.setTokenizerName((String) m.get("tokenizer_name")); index.setTokenizerConfigs((Map<String, String>) m.get("tokenizer_configs")); try { SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ"); String s = (String) m.get("min_index_day"); if (s != null) index.setMinIndexDay(f.parse(s)); } catch (ParseException e) { } index.setBasePath((String) m.get("base_path")); index.setBuildPastIndex((Boolean) m.get("build_past_index")); return index; } public void createIndex(IndexInfo info) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", info.getTableName()); params.put("index", info.getIndexName()); params.put("tokenizer_name", info.getTokenizerName()); params.put("tokenizer_configs", info.getTokenizerConfigs()); params.put("base_path", info.getBasePath()); params.put("min_index_day", info.getMinIndexDay()); params.put("build_past_index", info.isBuildPastIndex()); session.rpc("com.logpresso.index.msgbus.ManagementPlugin.createIndex", params); } public void dropIndex(String tableName, String indexName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); params.put("index", indexName); session.rpc("com.logpresso.index.msgbus.ManagementPlugin.dropIndex", params); } @SuppressWarnings("unchecked") public List<TableSchemaInfo> listTables() throws IOException { Message resp = session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.listTables"); List<TableSchemaInfo> tables = new ArrayList<TableSchemaInfo>(); Map<String, Object> m = (Map<String, Object>) resp.getParameters().get("tables"); for (String tableName : m.keySet()) { Map<String, Object> params = (Map<String, Object>) m.get(tableName); TableSchemaInfo tableInfo = getTableInfo(tableName, params); tables.add(tableInfo); } return tables; } @SuppressWarnings("unchecked") public TableSchemaInfo getTableInfo(String tableName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); Message resp = session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.getTableInfo", params); return getTableInfo(tableName, (Map<String, Object>) resp.get("table")); } private TableSchemaInfo getTableInfo(String tableName, Map<String, Object> params) { Map<String, String> metadata = new HashMap<String, String>(); for (Entry<String, Object> pair : params.entrySet()) metadata.put(pair.getKey(), pair.getValue() == null ? null : pair.getValue().toString()); return new TableSchemaInfo(tableName, metadata); } public void setTableMetadata(String tableName, Map<String, String> config) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); params.put("metadata", config); session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.setTableMetadata", params); } public void unsetTableMetadata(String tableName, Set<String> keySet) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); params.put("keys", keySet); session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.unsetTableMetadata", params); } public void createTable(String tableName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.createTable", params); } public void dropTable(String tableName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); session.rpc("org.araqne.logdb.msgbus.ManagementPlugin.dropTable", params); } @SuppressWarnings("unchecked") public List<LoggerFactoryInfo> listLoggerFactories() throws IOException { Message resp = session.rpc("org.araqne.log.api.msgbus.LoggerPlugin.getLoggerFactories"); List<LoggerFactoryInfo> factories = new ArrayList<LoggerFactoryInfo>(); List<Object> l = (List<Object>) resp.get("factories"); for (Object o : l) { parseLoggerFactoryInfo(factories, o); } return factories; } @SuppressWarnings("unchecked") public LoggerFactoryInfo getLoggerFactoryInfo(String factoryName) throws IOException { List<LoggerFactoryInfo> factories = listLoggerFactories(); LoggerFactoryInfo found = null; for (LoggerFactoryInfo f : factories) { if (f.getNamespace().equals("local") && f.getName().equals(factoryName)) { found = f; break; } } if (found == null) throw new IllegalStateException("logger factory not found: " + factoryName); Map<String, Object> params = new HashMap<String, Object>(); params.put("factory", factoryName); Message resp2 = session.rpc("org.araqne.log.api.msgbus.LoggerPlugin.getFactoryOptions", params); List<ConfigSpec> configSpecs = parseConfigList((List<Object>) resp2.get("options")); found.setConfigSpecs(configSpecs); return found; } @SuppressWarnings("unchecked") private void parseLoggerFactoryInfo(List<LoggerFactoryInfo> factories, Object o) { Map<String, Object> m = (Map<String, Object>) o; LoggerFactoryInfo f = new LoggerFactoryInfo(); f.setFullName((String) m.get("full_name")); f.setDisplayName((String) m.get("display_name")); f.setNamespace((String) m.get("namespace")); f.setName((String) m.get("name")); f.setDescription((String) m.get("description")); factories.add(f); } @SuppressWarnings("unchecked") public List<ParserFactoryInfo> listParserFactories() throws IOException { Message resp = session.rpc("org.araqne.log.api.msgbus.LoggerPlugin.getParserFactories"); List<Object> l = (List<Object>) resp.get("factories"); List<ParserFactoryInfo> parsers = new ArrayList<ParserFactoryInfo>(); for (Object o : l) { Map<String, Object> m = (Map<String, Object>) o; ParserFactoryInfo f = new ParserFactoryInfo(); f.setName((String) m.get("name")); f.setDisplayName((String) m.get("display_name")); f.setDescription((String) m.get("description")); f.setConfigSpecs(parseConfigList((List<Object>) m.get("options"))); parsers.add(f); } return parsers; } @SuppressWarnings("unchecked") private List<ConfigSpec> parseConfigList(List<Object> l) { List<ConfigSpec> specs = new ArrayList<ConfigSpec>(); for (Object o : l) { Map<String, Object> m = (Map<String, Object>) o; ConfigSpec spec = new ConfigSpec(); spec.setName((String) m.get("name")); spec.setDescription((String) m.get("description")); spec.setDisplayName((String) m.get("display_name")); spec.setType((String) m.get("type")); spec.setRequired((Boolean) m.get("required")); spec.setDefaultValue((String) m.get("default_value")); specs.add(spec); } return specs; } @SuppressWarnings("unchecked") public List<LoggerInfo> listLoggers() throws IOException { Message resp = session.rpc("org.araqne.log.api.msgbus.LoggerPlugin.getLoggers"); List<Object> l = (List<Object>) resp.get("loggers"); List<LoggerInfo> loggers = new ArrayList<LoggerInfo>(); for (Object o : l) { Map<String, Object> m = (Map<String, Object>) o; LoggerInfo lo = new LoggerInfo(); lo.setNamespace((String) m.get("namespace")); lo.setName((String) m.get("name")); lo.setFactoryName((String) m.get("factory_full_name")); lo.setDescription((String) m.get("description")); lo.setPassive((Boolean) m.get("is_passive")); lo.setInterval((Integer) m.get("interval")); lo.setStatus((String) m.get("status")); lo.setLastStartAt(parseDate((String) m.get("last_start"))); lo.setLastRunAt(parseDate((String) m.get("last_run"))); lo.setLastLogAt(parseDate((String) m.get("last_log"))); lo.setLogCount(Long.valueOf(m.get("log_count").toString())); if (m.get("log_volume") != null) lo.setLogVolume(Long.valueOf(m.get("log_volume").toString())); if (m.get("drop_volume") != null) lo.setDropVolume(Long.valueOf(m.get("drop_volume").toString())); loggers.add(lo); } return loggers; } private Date parseDate(String s) { if (s == null) return null; try { SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ"); return f.parse(s); } catch (ParseException e) { return null; } } public void createLogger(LoggerInfo logger) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("factory", logger.getFactoryName()); params.put("namespace", logger.getNamespace()); params.put("name", logger.getName()); params.put("description", logger.getDescription()); params.put("options", logger.getConfigs()); session.rpc("org.araqne.log.api.msgbus.LoggerPlugin.createLogger", params); } public void removeLogger(String fullName) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("logger", fullName); session.rpc("org.araqne.log.api.msgbus.LoggerPlugin.removeLogger", params); } public void startLogger(String fullName, int interval) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("logger", fullName); params.put("interval", interval); session.rpc("org.araqne.log.api.msgbus.LoggerPlugin.startLogger", params); } public void stopLogger(String fullName, int waitTime) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("logger", fullName); params.put("wait_time", waitTime); session.rpc("org.araqne.log.api.msgbus.LoggerPlugin.stopLogger", params); } public LogCursor query(String queryString) throws IOException { int id = createQuery(queryString); startQuery(id); LogQuery q = queries.get(id); q.waitUntil(null); long total = q.getLoadedCount(); return new LogCursorImpl(id, 0L, total, true); } private class LogCursorImpl implements LogCursor { private int id; private long offset; private long limit; private boolean removeOnClose; private long p; private Map<String, Object> cached; private Long currentCacheOffset; private Long nextCacheOffset; private int fetchUnit; private Map<String, Object> prefetch; public LogCursorImpl(int id, long offset, long limit, boolean removeOnClose) { this.id = id; this.offset = offset; this.limit = limit; this.removeOnClose = removeOnClose; this.p = offset; this.nextCacheOffset = offset; this.fetchUnit = 1000; } @SuppressWarnings("unchecked") @Override public boolean hasNext() { if (prefetch != null) return true; if (p < offset || p >= offset + limit) return false; try { if (cached == null || p >= currentCacheOffset + fetchUnit) { cached = getResult(id, nextCacheOffset, fetchUnit); currentCacheOffset = nextCacheOffset; nextCacheOffset += fetchUnit; } int relative = (int) (p - currentCacheOffset); List<Object> l = (List<Object>) cached.get("result"); if (relative >= l.size()) return false; prefetch = (Map<String, Object>) l.get(relative); p++; return true; } catch (IOException e) { logger.error("araqne logdb client: cannot fetch log query result", e); return false; } } @Override public Map<String, Object> next() { if (!hasNext()) throw new NoSuchElementException("end of log cursor"); Map<String, Object> m = prefetch; prefetch = null; return m; } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public void close() throws IOException { if (removeOnClose) removeQuery(id); } } public int createQuery(String queryString) throws IOException { Map<String, Object> params = new HashMap<String, Object>(); params.put("query", queryString); Message resp = session.rpc("org.araqne.logdb.msgbus.LogQueryPlugin.createQuery", params); int id = resp.getInt("id"); session.registerTrap("logstorage-query-" + id); session.registerTrap("logstorage-query-timeline-" + id); queries.put(id, new LogQuery(null, id, queryString)); return id; } public void startQuery(int id) throws IOException { startQuery(id, 10, 10); } public void startQuery(int id, int pageSize, int timelineSize) throws IOException { verifyQueryId(id); Map<String, Object> params = new HashMap<String, Object>(); params.put("id", id); params.put("offset", 0); params.put("limit", pageSize); params.put("timeline_limit", timelineSize); session.rpc("org.araqne.logdb.msgbus.LogQueryPlugin.startQuery", params); } public void stopQuery(int id) throws IOException { verifyQueryId(id); Map<String, Object> params = new HashMap<String, Object>(); params.put("id", id); session.rpc("org.araqne.logdb.msgbus.LogQueryPlugin.stopQuery", params); } public void removeQuery(int id) throws IOException { verifyQueryId(id); session.unregisterTrap("logstorage-query-" + id); session.unregisterTrap("logstorage-query-timeline-" + id); Map<String, Object> params = new HashMap<String, Object>(); params.put("id", id); session.rpc("org.araqne.logdb.msgbus.LogQueryPlugin.removeQuery", params); queries.remove(id); } public void waitUntil(int id, Long count) { verifyQueryId(id); queries.get(id).waitUntil(count); } public Map<String, Object> getResult(int id, long offset, int limit) throws IOException { verifyQueryId(id); Map<String, Object> params = new HashMap<String, Object>(); params.put("id", id); params.put("offset", offset); params.put("limit", limit); Message resp = session.rpc("org.araqne.logdb.msgbus.LogQueryPlugin.getResult", params); if (resp.getParameters().size() == 0) throw new MessageException("query-not-found", "", resp.getParameters()); return resp.getParameters(); } private void verifyQueryId(int id) { if (!queries.containsKey(id)) throw new MessageException("query-not-found", "query [" + id + "] does not exist", null); } public void close() throws IOException { if (session != null) session.close(); } @Override public void onTrap(Message msg) { long stamp = 0; if (msg.containsKey("stamp")) stamp = Long.parseLong(msg.get("stamp").toString()); String method = msg.getMethod(); if (method.startsWith("logstorage-query-") || method.startsWith("logdb-query-")) { int id = msg.getInt("id"); LogQuery q = queries.get(id); if (msg.getString("type").equals("eof")) { q.updateCount(msg.getLong("total_count"), stamp); q.updateStatus("Ended", stamp); } else if (msg.getString("type").equals("page_loaded")) { q.updateCount(msg.getLong("count"), stamp); q.updateStatus("Running", stamp); } else if (msg.getString("type").equals("status_change")) { q.updateCount(msg.getLong("count"), stamp); q.updateStatus(msg.getString("status"), stamp); } } } @Override public void onClose(Throwable t) { try { close(); } catch (IOException e) { } } }