/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with VoltDB. If not, see <http://www.gnu.org/licenses/>. */ package org.voltdb; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.voltdb.VoltTable.ColumnInfo; import org.voltcore.utils.Pair; // This StatsSource is a bit of a hackjob, in that it exists only to make StatsAgent // happy. The updating is never used, and the code in the Statistics sysproc // gets the client stats from the client interfaces and constructs the results // tables directly. This is identical to what IOStats also does. As // near as I can tell, this is because both the VoltNetwork and now the ClientInterface // have no catalog ID with which to associate these stats, so they just sort of hang out there // oddly. public class LiveClientsStats extends StatsSource { private Map<Long, Pair<String, long[]>> m_clientStats = new HashMap<Long, Pair<String,long[]>>(); public static final ColumnInfo liveClientColumnInfo[] = new ColumnInfo[] {new ColumnInfo("CONNECTION_ID", VoltType.BIGINT), new ColumnInfo("CLIENT_HOSTNAME", VoltType.STRING), new ColumnInfo("ADMIN", VoltType.TINYINT), new ColumnInfo("OUTSTANDING_REQUEST_BYTES", VoltType.BIGINT), new ColumnInfo("OUTSTANDING_RESPONSE_MESSAGES", VoltType.BIGINT), new ColumnInfo("OUTSTANDING_TRANSACTIONS", VoltType.BIGINT) }; /** * A dummy iterator that wraps an Iterator<Long> and provides the * Iterator<Object> */ private class DummyIterator implements Iterator<Object> { private final Iterator<Long> i; private DummyIterator(Iterator<Long> i) { this.i = i; } @Override public boolean hasNext() { return i.hasNext(); } @Override public Object next() { return i.next(); } @Override public void remove() { i.remove(); } } public LiveClientsStats() { super(false); } @Override protected void populateColumnSchema(ArrayList<ColumnInfo> columns) { super.populateColumnSchema(columns); for (ColumnInfo column : liveClientColumnInfo) { columns.add(column); } } @Override protected void updateStatsRow(Object rowKey, Object[] rowValues) { final Pair<String, long[]> info = m_clientStats.get(rowKey); final long[] counters = info.getSecond(); rowValues[columnNameToIndex.get("CONNECTION_ID")] = rowKey; rowValues[columnNameToIndex.get("CLIENT_HOSTNAME")] = info.getFirst(); rowValues[columnNameToIndex.get("ADMIN")] = counters[0]; rowValues[columnNameToIndex.get("OUTSTANDING_REQUEST_BYTES")] = counters[1]; rowValues[columnNameToIndex.get("OUTSTANDING_RESPONSE_MESSAGES")] = counters[2]; rowValues[columnNameToIndex.get("OUTSTANDING_TRANSACTIONS")] = counters[3]; super.updateStatsRow(rowKey, rowValues); } @Override protected Iterator<Object> getStatsRowKeyIterator(boolean interval) { m_clientStats = new HashMap<Long, Pair<String,long[]>>(); ClientInterface ci = VoltDB.instance().getClientInterface(); if (ci != null) { m_clientStats.putAll(ci.getLiveClientStats()); } return new DummyIterator(m_clientStats.keySet().iterator()); } }