org.elasticsearch.monitor.fs.FsInfo Maven / Gradle / Ivy
The newest version!
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.monitor.fs;
import com.google.common.collect.Iterators;
import org.elasticsearch.common.Nullable;
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.unit.ByteSizeValue;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentBuilderString;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class FsInfo implements Iterable, Streamable, ToXContent {
public static class Path implements Streamable, ToXContent {
String path;
@Nullable
String mount;
/** File system type from {@code java.nio.file.FileStore type()}, if available. */
@Nullable
String type;
long total = -1;
long free = -1;
long available = -1;
/** Uses Lucene's {@code IOUtils.spins} method to try to determine if the device backed by spinning media.
* This is null if we could not determine it, true if it possibly spins, else false. */
Boolean spins = null;
public Path() {
}
public Path(String path, @Nullable String mount, long total, long free, long available) {
this.path = path;
this.mount = mount;
this.total = total;
this.free = free;
this.available = available;
}
static public Path readInfoFrom(StreamInput in) throws IOException {
Path i = new Path();
i.readFrom(in);
return i;
}
@Override
public void readFrom(StreamInput in) throws IOException {
path = in.readOptionalString();
mount = in.readOptionalString();
type = in.readOptionalString();
total = in.readLong();
free = in.readLong();
available = in.readLong();
spins = in.readOptionalBoolean();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeOptionalString(path); // total aggregates do not have a path
out.writeOptionalString(mount);
out.writeOptionalString(type);
out.writeLong(total);
out.writeLong(free);
out.writeLong(available);
out.writeOptionalBoolean(spins);
}
public String getPath() {
return path;
}
public String getMount() {
return mount;
}
public String getType() {
return type;
}
public ByteSizeValue getTotal() {
return new ByteSizeValue(total);
}
public ByteSizeValue getFree() {
return new ByteSizeValue(free);
}
public ByteSizeValue getAvailable() {
return new ByteSizeValue(available);
}
public Boolean getSpins() {
return spins;
}
private long addLong(long current, long other) {
if (other == -1) {
return current;
}
if (current == -1) {
return other;
}
return current + other;
}
private double addDouble(double current, double other) {
if (other == -1) {
return current;
}
if (current == -1) {
return other;
}
return current + other;
}
public void add(Path path) {
total = addLong(total, path.total);
free = addLong(free, path.free);
available = addLong(available, path.available);
if (path.spins != null && path.spins.booleanValue()) {
// Spinning is contagious!
spins = Boolean.TRUE;
}
}
static final class Fields {
static final XContentBuilderString PATH = new XContentBuilderString("path");
static final XContentBuilderString MOUNT = new XContentBuilderString("mount");
static final XContentBuilderString TYPE = new XContentBuilderString("type");
static final XContentBuilderString TOTAL = new XContentBuilderString("total");
static final XContentBuilderString TOTAL_IN_BYTES = new XContentBuilderString("total_in_bytes");
static final XContentBuilderString FREE = new XContentBuilderString("free");
static final XContentBuilderString FREE_IN_BYTES = new XContentBuilderString("free_in_bytes");
static final XContentBuilderString AVAILABLE = new XContentBuilderString("available");
static final XContentBuilderString AVAILABLE_IN_BYTES = new XContentBuilderString("available_in_bytes");
static final XContentBuilderString SPINS = new XContentBuilderString("spins");
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
if (path != null) {
builder.field(Fields.PATH, path, XContentBuilder.FieldCaseConversion.NONE);
}
if (mount != null) {
builder.field(Fields.MOUNT, mount, XContentBuilder.FieldCaseConversion.NONE);
}
if (type != null) {
builder.field(Fields.TYPE, type, XContentBuilder.FieldCaseConversion.NONE);
}
if (total != -1) {
builder.byteSizeField(Fields.TOTAL_IN_BYTES, Fields.TOTAL, total);
}
if (free != -1) {
builder.byteSizeField(Fields.FREE_IN_BYTES, Fields.FREE, free);
}
if (available != -1) {
builder.byteSizeField(Fields.AVAILABLE_IN_BYTES, Fields.AVAILABLE, available);
}
if (spins != null) {
builder.field(Fields.SPINS, spins.toString());
}
builder.endObject();
return builder;
}
}
long timestamp;
Path total;
Path[] paths;
FsInfo() {
}
public FsInfo(long timestamp, Path[] paths) {
this.timestamp = timestamp;
this.paths = paths;
this.total = null;
}
public Path getTotal() {
return total();
}
public Path total() {
if (total != null) {
return total;
}
Path res = new Path();
Set seenDevices = new HashSet<>(paths.length);
for (Path subPath : paths) {
if (subPath.path != null) {
if (!seenDevices.add(subPath.path)) {
continue; // already added numbers for this device;
}
}
res.add(subPath);
}
total = res;
return res;
}
public long getTimestamp() {
return timestamp;
}
@Override
public Iterator iterator() {
return Iterators.forArray(paths);
}
public static FsInfo readFsInfo(StreamInput in) throws IOException {
FsInfo stats = new FsInfo();
stats.readFrom(in);
return stats;
}
@Override
public void readFrom(StreamInput in) throws IOException {
timestamp = in.readVLong();
paths = new Path[in.readVInt()];
for (int i = 0; i < paths.length; i++) {
paths[i] = Path.readInfoFrom(in);
}
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeVLong(timestamp);
out.writeVInt(paths.length);
for (Path path : paths) {
path.writeTo(out);
}
}
static final class Fields {
static final XContentBuilderString FS = new XContentBuilderString("fs");
static final XContentBuilderString TIMESTAMP = new XContentBuilderString("timestamp");
static final XContentBuilderString DATA = new XContentBuilderString("data");
static final XContentBuilderString TOTAL = new XContentBuilderString("total");
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(Fields.FS);
builder.field(Fields.TIMESTAMP, timestamp);
builder.field(Fields.TOTAL);
total().toXContent(builder, params);
builder.startArray(Fields.DATA);
for (Path path : paths) {
path.toXContent(builder, params);
}
builder.endArray();
builder.endObject();
return builder;
}
}