Package org.apache.hadoop.mapred

Source Code of org.apache.hadoop.mapred.TaskTrackerMemoryControlGroup

/*
* 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.hadoop.mapred;

import java.io.File;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapred.ControlGroup.MemoryControlGroup;
import org.apache.hadoop.syscall.LinuxSystemCall;
import java.io.BufferedReader;
import java.io.FileReader;

/**
* Limits memory usages of a TaskTracker and its Task through a Linux memory
* control group.
*
* Requirement:
* <ul>
* <li>A memory sub-system control group is available</li>
* <li>A path to a target control group is configured
* (mapred.tasktracker.cgroup.mem.root) or the default path will be used
* (/cgroup/memory/tasktrackers)</li>
* <li>A user launching Task has a permission to modify a control group (i.e.
* using chown)</li>
* <li>A memory limit property is set at the target control group</li>
* </ul>
*
* Current limitation of this implementation:
* <ul>
* <li>Support only a single TaskTracker per server</li>
* </ul>
*/
public class TaskTrackerMemoryControlGroup {
  private static Log LOG = LogFactory.getLog(TaskTrackerMemoryControlGroup.class);

  public static final String CGROUP_MEM_ROOT_PROPERTY = "mapred.container.cgroup.mem.root";
  public static final String DEFAULT_CGROUP_MEM_ROOT = "/cgroup/memory/task_container";
  public static final String CGROUP_MEM_JT_ROOT = "mapred.jobtracker.cgroup.mem.root";
  public static final String DEFAULT_JT_ROOT = "/cgroup/memory/jobtrackers";
  public static final String CGROUP_MEM_TT_ROOT = "mapred.tasktracker.cgroup.mem.root";
  public static final String DEFAULT_TT_ROOT = "/cgroup/memory/tasktrackers";
  // conf to control if we shall setup CGroup memory limit for individual tasks.
  // The default is false
  public static final String CGROUP_MEM_TASK_LIMIT= "mapred.tasktracker.cgroup.mem.tasklimit";

  public static final String CGROUP_TRASH_GROUP_NAME = "trash";

  private boolean isAvailable;
  private MemoryControlGroup ttcgp;
  private MemoryControlGroup jtcgp;
  private MemoryControlGroup containercgp;
  private MemoryControlGroup trashcgp;
  private boolean isTaskLimitOn = false;
  private String rootpath;
 
  private AtomicInteger numFailedToAddTask = new AtomicInteger();

  public TaskTrackerMemoryControlGroup(Configuration conf) {
    if (!MemoryControlGroup.isAvailable()) {
      LOG.warn("TaskMemoryControlGroup is disabled because a memory sub-system is not available");
      isAvailable = false;
      return;
    }

    String jtRootpath = conf.get(CGROUP_MEM_JT_ROOT, DEFAULT_JT_ROOT);
    jtcgp = new MemoryControlGroup(jtRootpath);
    jtcgp.enableMoveChargeAtImmigrate();

    if (!jtcgp.canControl()) {
      LOG.warn("TaskMemoryControlGroup is disabled because jtgroup doesn't have appropriate permission for "
          + jtRootpath);
      isAvailable = false;
      return;
    }

    String ttRootpath = conf.get(CGROUP_MEM_TT_ROOT, DEFAULT_TT_ROOT);
    ttcgp = new MemoryControlGroup(ttRootpath);
    ttcgp.enableMoveChargeAtImmigrate();

    if (!ttcgp.canControl()) {
      LOG.warn("TaskMemoryControlGroup is disabled because ttgroup doesn't have appropriate permission for "
          + ttRootpath);
      isAvailable = false;
      return;
    }
    if (getPID().equals("")) {
      LOG.warn("TaskMemoryControlGroup is disabled because JVM_PID is not set for TaskTracker");
      isAvailable = false;
      return;
    }
    ttcgp.addToGroup(getPID());

    rootpath = conf.get(CGROUP_MEM_ROOT_PROPERTY, DEFAULT_CGROUP_MEM_ROOT);
    containercgp = new MemoryControlGroup(rootpath);
    if (!containercgp.canControl()) {
      LOG.warn("TaskMemoryControlGroup is disabled because TaskTracker does not have appropriate permission for "
          + rootpath);
      isAvailable = false;
      return;
    }

    if (containercgp.getMemoryUsageLimit() <= 0) {
      LOG.warn("TaskMemoryControlGroup is disabled because memory.limit_in_bytes is not set up");
      isAvailable = false;
      return;
    }

    containercgp.enableMoveChargeAtImmigrate();
    containercgp.enableUseHierarchy();

    isAvailable = true;
    isTaskLimitOn = conf.getBoolean(CGROUP_MEM_TASK_LIMIT, false);

    trashcgp = containercgp.createSubGroup(CGROUP_TRASH_GROUP_NAME);
    trashcgp.disableMoveChargeAtImmigrate();
    // delete the old container group. Some tasks are failed to be removed when
    // the task tracker exited.
    File containDir = new File(rootpath);
    for (String child: containDir.list()) {
      if (child.startsWith("attempt")) {
        LOG.info("Remove " + child);
        try {
          BufferedReader reader = new BufferedReader(new FileReader(
            rootpath + "/" +child + "/tasks"));
          String thread = "";
          while( ( thread = reader.readLine() ) != null) {
            LOG.info(" kill " + thread);
            LinuxSystemCall.killProcessGroup(Integer.parseInt(thread));
          }
          reader.close();
        } catch (java.io.IOException e) {
          LOG.info("Exception in killing tasks");
        }
        removeTask(child);   
      }
    }
    LOG.info("TaskTrackerMemoryControlGroup is created with memory = " +
      containercgp.getMemoryUsageLimit());
  }
 
  public int getAndResetNumFailedToAddTask() {
    return this.numFailedToAddTask.getAndSet(0);
  }

  public void addTask(String taskname, String pid, long memoryLimit) {
    if (!isAvailable) {
      this.numFailedToAddTask.incrementAndGet();
      return ;
    }

    MemoryControlGroup taskcgp = containercgp.createSubGroup(taskname);
    taskcgp.enableMoveChargeAtImmigrate();
    if (isTaskLimitOn) {
      taskcgp.setMemoryUsageLimit(memoryLimit);
      LOG.info("Task " + taskname + " is added to control group with memory = " +
        memoryLimit );
    } else {
      LOG.info("Task " + taskname + " is added to control group without limit");
    }
    taskcgp.addToGroup(pid);
  }

  public void removeTask(String taskname) {
    if (!isAvailable)
      return ;

    MemoryControlGroup taskcgp = containercgp.getSubGroup(taskname);
    trashcgp.addToGroup(taskcgp.getThreadGroupList());
    taskcgp.deleteGroup();
  }

  private static String getPID() {
    return System.getenv().get("JVM_PID");
  }
 
  public boolean getTaskLimitOn(){
    return isTaskLimitOn;
  }
 
  public String getRootPath(){
    return rootpath;
  }
 
  public MemoryControlGroup getContainerMemoryControlGroup() {
    return containercgp;
  }

  public MemoryControlGroup getJTMemoryControlGroup() {
    return jtcgp;
  }

  public MemoryControlGroup getTTMemoryControlGroup() {
    return ttcgp;
  }

  public boolean checkAvailable() {
    return isAvailable;
  }
 
}
TOP

Related Classes of org.apache.hadoop.mapred.TaskTrackerMemoryControlGroup

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.