/*
* Licensed to Crate under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership. Crate licenses this file
* to you 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.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial
* agreement.
*/
package io.crate.monitor;
import com.google.common.base.Objects;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Streamable;
import org.elasticsearch.common.util.concurrent.XRejectedExecutionHandler;
import org.elasticsearch.threadpool.ThreadPool;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class ThreadPools implements Streamable, Iterable<Map.Entry<String, ThreadPools.ThreadPoolExecutorContext>> {
private final Map<String, ThreadPoolExecutorContext> contexts;
public static ThreadPools newInstance(ThreadPool threadPool) {
ThreadPools threadPools = ThreadPools.newInstance();
for (ThreadPool.Info info : threadPool.info()) {
String name = info.getName();
ThreadPoolExecutor executor = (ThreadPoolExecutor) threadPool.executor(name);
threadPools.add(name, ThreadPoolExecutorContext.newInstance(executor));
}
return threadPools;
}
public static ThreadPools newInstance() {
return new ThreadPools();
}
private ThreadPools() {
this.contexts = new HashMap<>();
}
public void add(String threadPool, ThreadPoolExecutorContext context) {
this.contexts.put(threadPool, context);
}
@Override
public void readFrom(StreamInput in) throws IOException {
int size = in.readVInt();
for (int i = 0; i < size; i++) {
String key = in.readString();
ThreadPoolExecutorContext value = new ThreadPoolExecutorContext();
value.readFrom(in);
contexts.put(key, value);
}
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(size());
for (Map.Entry<String, ThreadPoolExecutorContext> entry : contexts.entrySet()) {
out.writeString(entry.getKey());
entry.getValue().writeTo(out);
}
}
public int size() {
return contexts.size();
}
@Override
public Iterator<Map.Entry<String, ThreadPoolExecutorContext>> iterator() {
return contexts.entrySet().iterator();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ThreadPools that = (ThreadPools) o;
return Objects.equal(contexts, that.contexts);
}
@Override
public int hashCode() {
return Objects.hashCode(contexts);
}
public static ThreadPools readThreadPools(StreamInput in) throws IOException {
ThreadPools threadPools = new ThreadPools();
threadPools.readFrom(in);
return threadPools;
}
public static class ThreadPoolExecutorContext implements Streamable {
private int queueSize;
private int activeCount;
private int largestPoolSize;
private int poolSize;
private long completedTaskCount;
private long rejectedCount;
public static ThreadPoolExecutorContext newInstance(ThreadPoolExecutor executor) {
long rejectedCount = -1;
RejectedExecutionHandler rejectedExecutionHandler = executor.getRejectedExecutionHandler();
if (rejectedExecutionHandler instanceof XRejectedExecutionHandler) {
rejectedCount = ((XRejectedExecutionHandler) rejectedExecutionHandler).rejected();
}
return new ThreadPoolExecutorContext(
executor.getActiveCount(),
executor.getQueue().size(),
executor.getLargestPoolSize(),
executor.getPoolSize(),
executor.getCompletedTaskCount(),
rejectedCount);
}
public ThreadPoolExecutorContext() {
}
public ThreadPoolExecutorContext(int queueSize,
int activeCount,
int largestPoolSize,
int poolSize,
long completedTaskCount,
long rejectedCount) {
this.queueSize = queueSize;
this.activeCount = activeCount;
this.largestPoolSize = largestPoolSize;
this.poolSize = poolSize;
this.completedTaskCount = completedTaskCount;
this.rejectedCount = rejectedCount;
}
public int queueSize() {
return queueSize;
}
public int activeCount() {
return activeCount;
}
public int largestPoolSize() {
return largestPoolSize;
}
public int poolSize() {
return poolSize;
}
public long completedTaskCount() {
return completedTaskCount;
}
public long rejectedCount() {
return rejectedCount;
}
@Override
public void readFrom(StreamInput in) throws IOException {
queueSize = in.readInt();
activeCount = in.readInt();
largestPoolSize = in.readInt();
poolSize = in.readInt();
completedTaskCount = in.readLong();
rejectedCount = in.readLong();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeInt(queueSize);
out.writeInt(activeCount);
out.writeInt(largestPoolSize);
out.writeInt(poolSize);
out.writeLong(completedTaskCount);
out.writeLong(rejectedCount);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ThreadPoolExecutorContext that = (ThreadPoolExecutorContext) o;
return Objects.equal(queueSize, that.queueSize) &&
Objects.equal(activeCount, that.activeCount) &&
Objects.equal(largestPoolSize, that.largestPoolSize) &&
Objects.equal(poolSize, that.poolSize) &&
Objects.equal(completedTaskCount, that.completedTaskCount) &&
Objects.equal(rejectedCount, that.rejectedCount);
}
@Override
public int hashCode() {
return Objects.hashCode(queueSize, activeCount, largestPoolSize, poolSize, completedTaskCount, rejectedCount);
}
}
}