blob: 07f1abe315d0a89405bc494390a05511ee3c8c0b [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.storm.container.cgroup;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.storm.container.cgroup.core.CgroupCore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CgroupCommon implements CgroupCommonOperation {
public static final String TASKS = "/tasks";
public static final String NOTIFY_ON_RELEASE = "/notify_on_release";
public static final String RELEASE_AGENT = "/release_agent";
public static final String CGROUP_CLONE_CHILDREN = "/cgroup.clone_children";
public static final String CGROUP_EVENT_CONTROL = "/cgroup.event_control";
public static final String CGROUP_PROCS = "/cgroup.procs";
private static final Logger LOG = LoggerFactory.getLogger(CgroupCommon.class);
private final Hierarchy hierarchy;
private final String name;
private final String dir;
private final CgroupCommon parent;
private final boolean isRoot;
public CgroupCommon(String name, Hierarchy hierarchy, CgroupCommon parent) {
this.name = parent.getName() + "/" + name;
this.hierarchy = hierarchy;
this.parent = parent;
this.dir = parent.getDir() + "/" + name;
this.isRoot = false;
}
public CgroupCommon(Hierarchy hierarchy, String dir) {
this.name = "";
this.hierarchy = hierarchy;
this.parent = null;
this.dir = dir;
this.isRoot = true;
}
@Override
public void addTask(int taskId) throws IOException {
CgroupUtils.writeFileByLine(CgroupUtils.getDir(this.dir, TASKS), String.valueOf(taskId));
}
@Override
public Set<Integer> getTasks() throws IOException {
List<String> stringTasks = CgroupUtils.readFileByLine(CgroupUtils.getDir(this.dir, TASKS));
Set<Integer> tasks = new HashSet<Integer>();
for (String task : stringTasks) {
tasks.add(Integer.valueOf(task));
}
return tasks;
}
@Override
public void addProcs(int pid) throws IOException {
CgroupUtils.writeFileByLine(CgroupUtils.getDir(this.dir, CGROUP_PROCS), String.valueOf(pid));
}
@Override
public Set<Long> getPids() throws IOException {
List<String> stringPids = CgroupUtils.readFileByLine(CgroupUtils.getDir(this.dir, CGROUP_PROCS));
Set<Long> pids = new HashSet<>();
for (String task : stringPids) {
pids.add(Long.valueOf(task));
}
return pids;
}
@Override
public boolean getNotifyOnRelease() throws IOException {
return CgroupUtils.readFileByLine(CgroupUtils.getDir(this.dir, NOTIFY_ON_RELEASE)).get(0).equals("1") ? true : false;
}
@Override
public void setNotifyOnRelease(boolean flag) throws IOException {
CgroupUtils.writeFileByLine(CgroupUtils.getDir(this.dir, NOTIFY_ON_RELEASE), flag ? "1" : "0");
}
@Override
public String getReleaseAgent() throws IOException {
if (!this.isRoot) {
LOG.warn("Cannot get {} in {} since its not the root group", RELEASE_AGENT, this.isRoot);
return null;
}
return CgroupUtils.readFileByLine(CgroupUtils.getDir(this.dir, RELEASE_AGENT)).get(0);
}
@Override
public void setReleaseAgent(String command) throws IOException {
if (!this.isRoot) {
LOG.warn("Cannot set {} in {} since its not the root group", RELEASE_AGENT, this.isRoot);
return;
}
CgroupUtils.writeFileByLine(CgroupUtils.getDir(this.dir, RELEASE_AGENT), command);
}
@Override
public boolean getCgroupCloneChildren() throws IOException {
return CgroupUtils.readFileByLine(CgroupUtils.getDir(this.dir, CGROUP_CLONE_CHILDREN)).get(0).equals("1") ? true : false;
}
@Override
public void setCgroupCloneChildren(boolean flag) throws IOException {
if (!getCores().keySet().contains(SubSystemType.cpuset)) {
return;
}
CgroupUtils.writeFileByLine(CgroupUtils.getDir(this.dir, CGROUP_CLONE_CHILDREN), flag ? "1" : "0");
}
@Override
public void setEventControl(String eventFd, String controlFd, String... args) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append(eventFd);
sb.append(' ');
sb.append(controlFd);
for (String arg : args) {
sb.append(' ');
sb.append(arg);
}
CgroupUtils.writeFileByLine(CgroupUtils.getDir(this.dir, CGROUP_EVENT_CONTROL), sb.toString());
}
public Hierarchy getHierarchy() {
return hierarchy;
}
public String getName() {
return name;
}
public String getDir() {
return dir;
}
public CgroupCommon getParent() {
return parent;
}
public Set<CgroupCommon> getChildren() {
File file = new File(this.dir);
File[] files = file.listFiles();
if (files == null) {
LOG.info("{} is not a directory", this.dir);
return null;
}
Set<CgroupCommon> children = new HashSet<CgroupCommon>();
for (File child : files) {
if (child.isDirectory()) {
children.add(new CgroupCommon(child.getName(), this.hierarchy, this));
}
}
return children;
}
public boolean isRoot() {
return isRoot;
}
public Map<SubSystemType, CgroupCore> getCores() {
return CgroupCoreFactory.getInstance(this.hierarchy.getSubSystems(), this.dir);
}
public void delete() throws IOException {
this.free();
if (!this.isRoot) {
this.parent.getChildren().remove(this);
}
}
private void free() throws IOException {
for (CgroupCommon child : getChildren()) {
child.free();
}
if (this.isRoot) {
return;
}
Set<Integer> tasks = this.getTasks();
if (tasks != null) {
for (Integer task : tasks) {
this.parent.addTask(task);
}
}
CgroupUtils.deleteDir(this.dir);
}
@Override
public boolean equals(Object o) {
boolean ret = false;
if (o != null && (o instanceof CgroupCommon)) {
boolean hierarchyFlag = false;
if (((CgroupCommon) o).hierarchy != null && this.hierarchy != null) {
hierarchyFlag = ((CgroupCommon) o).hierarchy.equals(this.hierarchy);
} else if (((CgroupCommon) o).hierarchy == null && this.hierarchy == null) {
hierarchyFlag = true;
} else {
hierarchyFlag = false;
}
boolean nameFlag = false;
if (((CgroupCommon) o).name != null && this.name != null) {
nameFlag = ((CgroupCommon) o).name.equals(this.name);
} else if (((CgroupCommon) o).name == null && this.name == null) {
nameFlag = true;
} else {
nameFlag = false;
}
boolean dirFlag = false;
if (((CgroupCommon) o).dir != null && this.dir != null) {
dirFlag = ((CgroupCommon) o).dir.equals(this.dir);
} else if (((CgroupCommon) o).dir == null && this.dir == null) {
dirFlag = true;
} else {
dirFlag = false;
}
ret = hierarchyFlag && nameFlag && dirFlag;
}
return ret;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (this.name != null ? this.name.hashCode() : 0);
result = prime * result + (this.hierarchy != null ? this.hierarchy.hashCode() : 0);
result = prime * result + (this.dir != null ? this.dir.hashCode() : 0);
return result;
}
@Override
public String toString() {
return this.getName();
}
}