content: /**
   * 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 com.alibaba.jstorm.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 com.alibaba.jstorm.container.CgroupUtils;
  import com.alibaba.jstorm.container.Constants;
  import com.alibaba.jstorm.container.Hierarchy;
  import com.alibaba.jstorm.container.SubSystemType;
  import com.alibaba.jstorm.container.cgroup.core.CgroupCore;
  
  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 final Hierarchy hierarchy;
  
      private final String name;
  
      private final String dir;
  
      private final CgroupCommon parent;
  
      private final Map<SubSystemType, CgroupCore> cores;
  
      private final boolean isRoot;
  
      private final Set<CgroupCommon> children = new HashSet<CgroupCommon>();
  
      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.init();
          cores = CgroupCoreFactory.getInstance(this.hierarchy.getSubSystems(), this.dir);
          this.isRoot = false;
      }
  
      /**
       * rootCgroup
       */
      public CgroupCommon(Hierarchy hierarchy, String dir) {
          this.name = "";
          this.hierarchy = hierarchy;
          this.parent = null;
          this.dir = dir;
          this.init();
          cores = CgroupCoreFactory.getInstance(this.hierarchy.getSubSystems(), this.dir);
          this.isRoot = true;
      }
  
      @Override
      public void addTask(int taskId) throws IOException {
          CgroupUtils.writeFileByLine(Constants.getDir(this.dir, TASKS), String.valueOf(taskId));
      }
  
      @Override
      public Set<Integer> getTasks() throws IOException {
          List<String> stringTasks = CgroupUtils.readFileByLine(Constants.getDir(this.dir, TASKS));
          Set<Integer> tasks = new HashSet<>();
          for (String task : stringTasks) {
              tasks.add(Integer.valueOf(task));
          }
          return tasks;
      }
  
      @Override
      public void addProcs(int pid) throws IOException {
          CgroupUtils.writeFileByLine(Constants.getDir(this.dir, CGROUP_PROCS), String.valueOf(pid));
      }
  
      @Override
      public Set<Integer> getPids() throws IOException {
          List<String> stringPids = CgroupUtils.readFileByLine(Constants.getDir(this.dir, CGROUP_PROCS));
          Set<Integer> pids = new HashSet<>();
          for (String task : stringPids) {
              pids.add(Integer.valueOf(task));
          }
          return pids;
      }
  
      @Override
      public void setNotifyOnRelease(boolean flag) throws IOException {
          CgroupUtils.writeFileByLine(Constants.getDir(this.dir, NOTIFY_ON_RELEASE), flag ? "1" : "0");
      }
  
      @Override
      public boolean getNotifyOnRelease() throws IOException {
          return CgroupUtils.readFileByLine(Constants.getDir(this.dir, NOTIFY_ON_RELEASE)).get(0).equals("1");
      }
  
      @Override
      public void setReleaseAgent(String command) throws IOException {
          if (!this.isRoot)
              return;
          CgroupUtils.writeFileByLine(Constants.getDir(this.dir, RELEASE_AGENT), command);
      }
  
      @Override
      public String getReleaseAgent() throws IOException {
          if (!this.isRoot)
              return null;
          return CgroupUtils.readFileByLine(Constants.getDir(this.dir, RELEASE_AGENT)).get(0);
      }
  
      @Override
      public void setCgroupCloneChildren(boolean flag) throws IOException {
          if (!this.cores.keySet().contains(SubSystemType.cpuset))
              return;
          CgroupUtils.writeFileByLine(Constants.getDir(this.dir, CGROUP_CLONE_CHILDREN), flag ? "1" : "0");
      }
  
      @Override
      public boolean getCgroupCloneChildren() throws IOException {
          return CgroupUtils.readFileByLine(Constants.getDir(this.dir, CGROUP_CLONE_CHILDREN)).get(0).equals("1");
      }
  
      @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(Constants.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() {
          return children;
      }
  
      public boolean isRoot() {
          return isRoot;
      }
  
      public Map<SubSystemType, CgroupCore> getCores() {
          return cores;
      }
  
      public void delete() throws IOException {
          this.free();
          if (!this.isRoot)
              this.parent.getChildren().remove(this);
      }
  
      private void free() throws IOException {
          for (CgroupCommon child : this.children)
              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);
      }
  
      private void init() {
          File file = new File(this.dir);
          File[] files = file.listFiles();
          if (files == null)
              return;
          for (File child : files) {
              if (child.isDirectory()) {
                  this.children.add(new CgroupCommon(child.getName(), this.hierarchy, this));
              }
          }
      }
  
  }
  