blob: cdf50fdc9e287392b6f9183676b769cec2809966 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.
*/
package org.apache.lucene.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
/**
* Helper methods for constructing nested resource descriptions
* and debugging RAM usage.
* <p>
* {@code toString(Accountable}} can be used to quickly debug the nested
* structure of any Accountable.
* <p>
* The {@code namedAccountable} and {@code namedAccountables} methods return
* type-safe, point-in-time snapshots of the provided resources.
*/
public class Accountables {
private Accountables() {}
/**
* Returns a String description of an Accountable and any nested resources.
* This is intended for development and debugging.
*/
public static String toString(Accountable a) {
StringBuilder sb = new StringBuilder();
toString(sb, a, 0);
return sb.toString();
}
private static StringBuilder toString(StringBuilder dest, Accountable a, int depth) {
for (int i = 1; i < depth; i++) {
dest.append(" ");
}
if (depth > 0) {
dest.append("|-- ");
}
dest.append(a.toString());
dest.append(": ");
dest.append(RamUsageEstimator.humanReadableUnits(a.ramBytesUsed()));
dest.append(System.lineSeparator());
for (Accountable child : a.getChildResources()) {
toString(dest, child, depth + 1);
}
return dest;
}
/**
* Augments an existing accountable with the provided description.
* <p>
* The resource description is constructed in this format:
* {@code description [toString()]}
* <p>
* This is a point-in-time type safe view: consumers
* will not be able to cast or manipulate the resource in any way.
*/
public static Accountable namedAccountable(String description, Accountable in) {
return namedAccountable(description + " [" + in + "]", in.getChildResources(), in.ramBytesUsed());
}
/**
* Returns an accountable with the provided description and bytes.
*/
public static Accountable namedAccountable(String description, long bytes) {
return namedAccountable(description, Collections.<Accountable>emptyList(), bytes);
}
/**
* Converts a map of resources to a collection.
* <p>
* The resource descriptions are constructed in this format:
* {@code prefix 'key' [toString()]}
* <p>
* This is a point-in-time type safe view: consumers
* will not be able to cast or manipulate the resources in any way.
*/
public static Collection<Accountable> namedAccountables(String prefix, Map<?,? extends Accountable> in) {
List<Accountable> resources = new ArrayList<>();
for (Map.Entry<?,? extends Accountable> kv : in.entrySet()) {
resources.add(namedAccountable(prefix + " '" + kv.getKey() + "'", kv.getValue()));
}
Collections.sort(resources, new Comparator<Accountable>() {
@Override
public int compare(Accountable o1, Accountable o2) {
return o1.toString().compareTo(o2.toString());
}
});
return Collections.unmodifiableList(resources);
}
/**
* Returns an accountable with the provided description, children and bytes.
* <p>
* The resource descriptions are constructed in this format:
* {@code description [toString()]}
* <p>
* This is a point-in-time type safe view: consumers
* will not be able to cast or manipulate the resources in any way, provided
* that the passed in children Accountables (and all their descendants) were created
* with one of the namedAccountable functions.
*/
public static Accountable namedAccountable(final String description, final Collection<Accountable> children, final long bytes) {
return new Accountable() {
@Override
public long ramBytesUsed() {
return bytes;
}
@Override
public Collection<Accountable> getChildResources() {
return children;
}
@Override
public String toString() {
return description;
}
};
}
}