You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by bm...@apache.org on 2014/12/04 00:14:08 UTC

[2/8] mesos git commit: Cleaned up the utility structs in the allocator.

Cleaned up the utility structs in the allocator.

Review: https://reviews.apache.org/r/28663


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/0cb4c9c0
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/0cb4c9c0
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/0cb4c9c0

Branch: refs/heads/master
Commit: 0cb4c9c05960a31cd507f36e9a1b7da6aa3f689f
Parents: f575ae4
Author: Benjamin Mahler <be...@gmail.com>
Authored: Tue Dec 2 17:51:55 2014 -0800
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Wed Dec 3 14:59:19 2014 -0800

----------------------------------------------------------------------
 src/master/hierarchical_allocator_process.hpp | 136 ++++++++++-----------
 1 file changed, 64 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/0cb4c9c0/src/master/hierarchical_allocator_process.hpp
----------------------------------------------------------------------
diff --git a/src/master/hierarchical_allocator_process.hpp b/src/master/hierarchical_allocator_process.hpp
index 4f284ce..c71739b 100644
--- a/src/master/hierarchical_allocator_process.hpp
+++ b/src/master/hierarchical_allocator_process.hpp
@@ -57,52 +57,6 @@ typedef HierarchicalAllocatorProcess<DRFSorter, DRFSorter>
 HierarchicalDRFAllocatorProcess;
 
 
-struct Slave
-{
-  Slave() {}
-
-  explicit Slave(const SlaveInfo& _info)
-    : available(_info.resources()),
-      activated(true),
-      checkpoint(_info.checkpoint()),
-      info(_info) {}
-
-  Resources resources() const { return info.resources(); }
-
-  std::string hostname() const { return info.hostname(); }
-
-  // Contains all of the resources currently free on this slave.
-  Resources available;
-
-  // Whether the slave is activated. Resources are not offered for
-  // deactivated slaves until they are reactivated.
-  bool activated;
-
-  bool checkpoint;
-private:
-  SlaveInfo info;
-};
-
-
-struct Framework
-{
-  Framework() {}
-
-  explicit Framework(const FrameworkInfo& _info)
-    : checkpoint(_info.checkpoint()),
-      info(_info) {}
-
-  std::string role() const { return info.role(); }
-
-  // Filters that have been added by this framework.
-  hashset<Filter*> filters;
-
-  bool checkpoint;
-private:
-  FrameworkInfo info;
-};
-
-
 // Implements the basic allocator algorithm - first pick a role by
 // some criteria, then pick one of their frameworks to allocate to.
 template <typename RoleSorter, typename FrameworkSorter>
@@ -202,14 +156,31 @@ protected:
   Flags flags;
   process::PID<Master> master;
 
-  // Contains all frameworks.
+  struct Framework
+  {
+    std::string role;
+    bool checkpoint;  // Whether the framework desires checkpointing.
+
+    hashset<Filter*> filters; // Active filters for the framework.
+  };
+
   hashmap<FrameworkID, Framework> frameworks;
 
   // Maps role names to the Sorter object which contains
   // all of that role's frameworks.
   hashmap<std::string, FrameworkSorter*> sorters;
 
-  // Contains all active slaves.
+  struct Slave
+  {
+    Resources total;
+    Resources available;
+
+    bool activated;  // Whether to offer resources.
+    bool checkpoint; // Whether slave supports checkpointing.
+
+    std::string hostname;
+  };
+
   hashmap<SlaveID, Slave> slaves;
 
   hashmap<std::string, RoleInfo> roles;
@@ -319,7 +290,9 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::frameworkAdded(
   sorters[role]->add(used);
   sorters[role]->allocated(frameworkId.value(), used);
 
-  frameworks[frameworkId] = Framework(frameworkInfo);
+  frameworks[frameworkId] = Framework();
+  frameworks[frameworkId].role = frameworkInfo.role();
+  frameworks[frameworkId].checkpoint = frameworkInfo.checkpoint();
 
   LOG(INFO) << "Added framework " << frameworkId;
 
@@ -335,7 +308,7 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::frameworkRemoved(
   CHECK(initialized);
 
   CHECK(frameworks.contains(frameworkId));
-  const std::string& role = frameworks[frameworkId].role();
+  const std::string& role = frameworks[frameworkId].role;
 
   // Might not be in 'sorters[role]' because it was previously
   // deactivated and never re-added.
@@ -381,7 +354,7 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::frameworkDeactivated(
   CHECK(initialized);
 
   CHECK(frameworks.contains(frameworkId));
-  const std::string& role = frameworks[frameworkId].role();
+  const std::string& role = frameworks[frameworkId].role;
 
   sorters[role]->deactivate(frameworkId.value());
 
@@ -401,6 +374,21 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::frameworkDeactivated(
 }
 
 
+namespace internal {
+
+// TODO(bmahler): Generalize this.
+template <typename Iterable>
+Resources sum(const Iterable& resources)
+{
+  Resources total;
+  foreach (const Resources& r, resources) {
+    total += r;
+  }
+  return total;
+}
+
+} // namespace internal {
+
 template <class RoleSorter, class FrameworkSorter>
 void
 HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::slaveAdded(
@@ -409,33 +397,34 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::slaveAdded(
     const hashmap<FrameworkID, Resources>& used)
 {
   CHECK(initialized);
-
   CHECK(!slaves.contains(slaveId));
 
-  slaves[slaveId] = Slave(slaveInfo);
-
-  roleSorter->add(slaveInfo.resources());
+  const Resources& total = slaveInfo.resources();
 
-  Resources unused = slaveInfo.resources();
+  roleSorter->add(total);
 
   foreachpair (const FrameworkID& frameworkId,
                const Resources& resources,
                used) {
     if (frameworks.contains(frameworkId)) {
-      const std::string& role = frameworks[frameworkId].role();
+      const std::string& role = frameworks[frameworkId].role;
+
       sorters[role]->add(resources);
       sorters[role]->allocated(frameworkId.value(), resources);
       roleSorter->allocated(role, resources);
     }
-
-    unused -= resources; // Only want to allocate resources that are not used!
   }
 
-  slaves[slaveId].available = unused;
+  slaves[slaveId] = Slave();
+  slaves[slaveId].total = total;
+  slaves[slaveId].available = total - internal::sum(used.values());
+  slaves[slaveId].activated = true;
+  slaves[slaveId].checkpoint = slaveInfo.checkpoint();
+  slaves[slaveId].hostname = slaveInfo.hostname();
 
-  LOG(INFO) << "Added slave " << slaveId << " (" << slaveInfo.hostname()
-            << ") with " << slaveInfo.resources() << " (and " << unused
-            << " available)";
+  LOG(INFO) << "Added slave " << slaveId << " (" << slaves[slaveId].hostname
+            << ") with " << slaves[slaveId].total
+            << " (and " << slaves[slaveId].available << " available)";
 
   allocate(slaveId);
 }
@@ -449,7 +438,7 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::slaveRemoved(
   CHECK(initialized);
   CHECK(slaves.contains(slaveId));
 
-  roleSorter->remove(slaves[slaveId].resources());
+  roleSorter->remove(slaves[slaveId].total);
 
   slaves.erase(slaveId);
 
@@ -542,12 +531,16 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::resourcesRecovered(
   // Master::offer before we received AllocatorProcess::frameworkRemoved
   // or AllocatorProcess::frameworkDeactivated, in which case we will
   // have already recovered all of its resources).
-  if (frameworks.contains(frameworkId) &&
-      sorters[frameworks[frameworkId].role()]->contains(frameworkId.value())) {
-    const std::string& role = frameworks[frameworkId].role();
-    sorters[role]->unallocated(frameworkId.value(), resources);
-    sorters[role]->remove(resources);
-    roleSorter->unallocated(role, resources);
+  if (frameworks.contains(frameworkId)) {
+    const std::string& role = frameworks[frameworkId].role;
+
+    CHECK(sorters.contains(role));
+
+    if (sorters[role]->contains(frameworkId.value())) {
+      sorters[role]->unallocated(frameworkId.value(), resources);
+      sorters[role]->remove(resources);
+      roleSorter->unallocated(role, resources);
+    }
   }
 
   // Update resources allocatable on slave (if slave still exists,
@@ -779,11 +772,10 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::isWhitelisted(
     const SlaveID& slaveId)
 {
   CHECK(initialized);
-
   CHECK(slaves.contains(slaveId));
 
   return whitelist.isNone() ||
-         whitelist.get().contains(slaves[slaveId].hostname());
+         whitelist.get().contains(slaves[slaveId].hostname);
 }
 
 


Re: [2/8] mesos git commit: Cleaned up the utility structs in the allocator.

Posted by Bernd Mathiske <be...@mesosphere.io>.
Hi Ben!

FYI, one of your recent commits seems to have caused the build on Macs to fail:

libtool: compile:  g++ -DPACKAGE_NAME=\"mesos\" -DPACKAGE_TARNAME=\"mesos\" -DPACKAGE_VERSION=\"0.22.0\" "-DPACKAGE_STRING=\"mesos 0.22.0\"" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"mesos\" -DVERSION=\"0.22.0\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DHAVE_PTHREAD=1 -DHAVE_LIBZ=1 -DHAVE_LIBCURL=1 -DHAVE_APR_POOLS_H=1 -DHAVE_LIBAPR_1=1 -DHAVE_SVN_VERSION_H=1 -DHAVE_LIBSVN_SUBR_1=1 -DHAVE_SVN_DELTA_H=1 -DHAVE_LIBSVN_DELTA_1=1 -DHAVE_LIBSASL2=1 -DMESOS_HAS_JAVA=1 -DHAVE_PYTHON=\"2.7\" -DMESOS_HAS_PYTHON=1 -I. -I../../src -Wall -Werror -DLIBDIR=\"/usr/local/lib\" -DPKGLIBEXECDIR=\"/usr/local/libexec/mesos\" -DPKGDATADIR=\"/usr/local/share/mesos\" -I../../include -I../../3rdparty/libprocess/include -I../../3rdparty/libprocess/3rdparty/stout/include -I../include -I../include/mesos -I../3rdparty/libprocess/3rdparty/boost-1.53.0 -I../3rdparty/libprocess/3rdparty/picojson-4f93734 -I../3rdparty/libprocess/3rdparty/protobuf-2.5.0/src -I../3rdparty/libprocess/3rdparty/glog-0.3.3/src -I../3rdparty/libprocess/3rdparty/glog-0.3.3/src -I../3rdparty/leveldb/include -I../3rdparty/zookeeper-3.4.5/src/c/include -I../3rdparty/zookeeper-3.4.5/src/c/generated -I../3rdparty/libprocess/3rdparty/protobuf-2.5.0/src -I/usr/include/subversion-1 -I/usr/include/apr-1 -I/usr/include/apr-1.0 -D_THREAD_SAFE -g1 -O0 -std=c++11 -stdlib=libc++ -DGTEST_USE_OWN_TR1_TUPLE=1 -MT authorizer/libmesos_no_3rdparty_la-authorizer.lo -MD -MP -MF authorizer/.deps/libmesos_no_3rdparty_la-authorizer.Tpo -c ../../src/authorizer/authorizer.cpp -o authorizer/libmesos_no_3rdparty_la-authorizer.o >/dev/null 2>&1
libtool: compile:  g++ -DPACKAGE_NAME=\"mesos\" -DPACKAGE_TARNAME=\"mesos\" -DPACKAGE_VERSION=\"0.22.0\" "-DPACKAGE_STRING=\"mesos 0.22.0\"" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"mesos\" -DVERSION=\"0.22.0\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DHAVE_PTHREAD=1 -DHAVE_LIBZ=1 -DHAVE_LIBCURL=1 -DHAVE_APR_POOLS_H=1 -DHAVE_LIBAPR_1=1 -DHAVE_SVN_VERSION_H=1 -DHAVE_LIBSVN_SUBR_1=1 -DHAVE_SVN_DELTA_H=1 -DHAVE_LIBSVN_DELTA_1=1 -DHAVE_LIBSASL2=1 -DMESOS_HAS_JAVA=1 -DHAVE_PYTHON=\"2.7\" -DMESOS_HAS_PYTHON=1 -I. -I../../src -Wall -Werror -DLIBDIR=\"/usr/local/lib\" -DPKGLIBEXECDIR=\"/usr/local/libexec/mesos\" -DPKGDATADIR=\"/usr/local/share/mesos\" -I../../include -I../../3rdparty/libprocess/include -I../../3rdparty/libprocess/3rdparty/stout/include -I../include -I../include/mesos -I../3rdparty/libprocess/3rdparty/boost-1.53.0 -I../3rdparty/libprocess/3rdparty/picojson-4f93734 -I../3rdparty/libprocess/3rdparty/protobuf-2.5.0/src -I../3rdparty/libprocess/3rdparty/glog-0.3.3/src -I../3rdparty/libprocess/3rdparty/glog-0.3.3/src -I../3rdparty/leveldb/include -I../3rdparty/zookeeper-3.4.5/src/c/include -I../3rdparty/zookeeper-3.4.5/src/c/generated -I../3rdparty/libprocess/3rdparty/protobuf-2.5.0/src -I/usr/include/subversion-1 -I/usr/include/apr-1 -I/usr/include/apr-1.0 -D_THREAD_SAFE -g1 -O0 -std=c++11 -stdlib=libc++ -DGTEST_USE_OWN_TR1_TUPLE=1 -MT logging/libmesos_no_3rdparty_la-logging.lo -MD -MP -MF logging/.deps/libmesos_no_3rdparty_la-logging.Tpo -c ../../src/logging/logging.cpp  -fno-common -DPIC -o logging/.libs/libmesos_no_3rdparty_la-logging.o
In file included from ../../src/local/local.cpp:43:
../../src/master/allocator.hpp:143:16: error: 
      'mesos::internal::master::allocator::AllocatorProcess::initialize' hides overloaded virtual function
      [-Werror,-Woverloaded-virtual]
  virtual void initialize(
               ^
../../3rdparty/libprocess/include/process/process.hpp:49:16: note: hidden overloaded virtual function
      'process::ProcessBase::initialize' declared here: different number of parameters (0 vs 3)
  virtual void initialize() {}

Bernd

> On Dec 3, 2014, at 3:14 PM, bmahler@apache.org wrote:
> 
> Cleaned up the utility structs in the allocator.
> 
> Review: https://reviews.apache.org/r/28663
> 
> 
> Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
> Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/0cb4c9c0
> Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/0cb4c9c0
> Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/0cb4c9c0
> 
> Branch: refs/heads/master
> Commit: 0cb4c9c05960a31cd507f36e9a1b7da6aa3f689f
> Parents: f575ae4
> Author: Benjamin Mahler <be...@gmail.com>
> Authored: Tue Dec 2 17:51:55 2014 -0800
> Committer: Benjamin Mahler <be...@gmail.com>
> Committed: Wed Dec 3 14:59:19 2014 -0800
> 
> ----------------------------------------------------------------------
> src/master/hierarchical_allocator_process.hpp | 136 ++++++++++-----------
> 1 file changed, 64 insertions(+), 72 deletions(-)
> ----------------------------------------------------------------------
> 
> 
> http://git-wip-us.apache.org/repos/asf/mesos/blob/0cb4c9c0/src/master/hierarchical_allocator_process.hpp
> ----------------------------------------------------------------------
> diff --git a/src/master/hierarchical_allocator_process.hpp b/src/master/hierarchical_allocator_process.hpp
> index 4f284ce..c71739b 100644
> --- a/src/master/hierarchical_allocator_process.hpp
> +++ b/src/master/hierarchical_allocator_process.hpp
> @@ -57,52 +57,6 @@ typedef HierarchicalAllocatorProcess<DRFSorter, DRFSorter>
> HierarchicalDRFAllocatorProcess;
> 
> 
> -struct Slave
> -{
> -  Slave() {}
> -
> -  explicit Slave(const SlaveInfo& _info)
> -    : available(_info.resources()),
> -      activated(true),
> -      checkpoint(_info.checkpoint()),
> -      info(_info) {}
> -
> -  Resources resources() const { return info.resources(); }
> -
> -  std::string hostname() const { return info.hostname(); }
> -
> -  // Contains all of the resources currently free on this slave.
> -  Resources available;
> -
> -  // Whether the slave is activated. Resources are not offered for
> -  // deactivated slaves until they are reactivated.
> -  bool activated;
> -
> -  bool checkpoint;
> -private:
> -  SlaveInfo info;
> -};
> -
> -
> -struct Framework
> -{
> -  Framework() {}
> -
> -  explicit Framework(const FrameworkInfo& _info)
> -    : checkpoint(_info.checkpoint()),
> -      info(_info) {}
> -
> -  std::string role() const { return info.role(); }
> -
> -  // Filters that have been added by this framework.
> -  hashset<Filter*> filters;
> -
> -  bool checkpoint;
> -private:
> -  FrameworkInfo info;
> -};
> -
> -
> // Implements the basic allocator algorithm - first pick a role by
> // some criteria, then pick one of their frameworks to allocate to.
> template <typename RoleSorter, typename FrameworkSorter>
> @@ -202,14 +156,31 @@ protected:
>   Flags flags;
>   process::PID<Master> master;
> 
> -  // Contains all frameworks.
> +  struct Framework
> +  {
> +    std::string role;
> +    bool checkpoint;  // Whether the framework desires checkpointing.
> +
> +    hashset<Filter*> filters; // Active filters for the framework.
> +  };
> +
>   hashmap<FrameworkID, Framework> frameworks;
> 
>   // Maps role names to the Sorter object which contains
>   // all of that role's frameworks.
>   hashmap<std::string, FrameworkSorter*> sorters;
> 
> -  // Contains all active slaves.
> +  struct Slave
> +  {
> +    Resources total;
> +    Resources available;
> +
> +    bool activated;  // Whether to offer resources.
> +    bool checkpoint; // Whether slave supports checkpointing.
> +
> +    std::string hostname;
> +  };
> +
>   hashmap<SlaveID, Slave> slaves;
> 
>   hashmap<std::string, RoleInfo> roles;
> @@ -319,7 +290,9 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::frameworkAdded(
>   sorters[role]->add(used);
>   sorters[role]->allocated(frameworkId.value(), used);
> 
> -  frameworks[frameworkId] = Framework(frameworkInfo);
> +  frameworks[frameworkId] = Framework();
> +  frameworks[frameworkId].role = frameworkInfo.role();
> +  frameworks[frameworkId].checkpoint = frameworkInfo.checkpoint();
> 
>   LOG(INFO) << "Added framework " << frameworkId;
> 
> @@ -335,7 +308,7 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::frameworkRemoved(
>   CHECK(initialized);
> 
>   CHECK(frameworks.contains(frameworkId));
> -  const std::string& role = frameworks[frameworkId].role();
> +  const std::string& role = frameworks[frameworkId].role;
> 
>   // Might not be in 'sorters[role]' because it was previously
>   // deactivated and never re-added.
> @@ -381,7 +354,7 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::frameworkDeactivated(
>   CHECK(initialized);
> 
>   CHECK(frameworks.contains(frameworkId));
> -  const std::string& role = frameworks[frameworkId].role();
> +  const std::string& role = frameworks[frameworkId].role;
> 
>   sorters[role]->deactivate(frameworkId.value());
> 
> @@ -401,6 +374,21 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::frameworkDeactivated(
> }
> 
> 
> +namespace internal {
> +
> +// TODO(bmahler): Generalize this.
> +template <typename Iterable>
> +Resources sum(const Iterable& resources)
> +{
> +  Resources total;
> +  foreach (const Resources& r, resources) {
> +    total += r;
> +  }
> +  return total;
> +}
> +
> +} // namespace internal {
> +
> template <class RoleSorter, class FrameworkSorter>
> void
> HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::slaveAdded(
> @@ -409,33 +397,34 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::slaveAdded(
>     const hashmap<FrameworkID, Resources>& used)
> {
>   CHECK(initialized);
> -
>   CHECK(!slaves.contains(slaveId));
> 
> -  slaves[slaveId] = Slave(slaveInfo);
> -
> -  roleSorter->add(slaveInfo.resources());
> +  const Resources& total = slaveInfo.resources();
> 
> -  Resources unused = slaveInfo.resources();
> +  roleSorter->add(total);
> 
>   foreachpair (const FrameworkID& frameworkId,
>                const Resources& resources,
>                used) {
>     if (frameworks.contains(frameworkId)) {
> -      const std::string& role = frameworks[frameworkId].role();
> +      const std::string& role = frameworks[frameworkId].role;
> +
>       sorters[role]->add(resources);
>       sorters[role]->allocated(frameworkId.value(), resources);
>       roleSorter->allocated(role, resources);
>     }
> -
> -    unused -= resources; // Only want to allocate resources that are not used!
>   }
> 
> -  slaves[slaveId].available = unused;
> +  slaves[slaveId] = Slave();
> +  slaves[slaveId].total = total;
> +  slaves[slaveId].available = total - internal::sum(used.values());
> +  slaves[slaveId].activated = true;
> +  slaves[slaveId].checkpoint = slaveInfo.checkpoint();
> +  slaves[slaveId].hostname = slaveInfo.hostname();
> 
> -  LOG(INFO) << "Added slave " << slaveId << " (" << slaveInfo.hostname()
> -            << ") with " << slaveInfo.resources() << " (and " << unused
> -            << " available)";
> +  LOG(INFO) << "Added slave " << slaveId << " (" << slaves[slaveId].hostname
> +            << ") with " << slaves[slaveId].total
> +            << " (and " << slaves[slaveId].available << " available)";
> 
>   allocate(slaveId);
> }
> @@ -449,7 +438,7 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::slaveRemoved(
>   CHECK(initialized);
>   CHECK(slaves.contains(slaveId));
> 
> -  roleSorter->remove(slaves[slaveId].resources());
> +  roleSorter->remove(slaves[slaveId].total);
> 
>   slaves.erase(slaveId);
> 
> @@ -542,12 +531,16 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::resourcesRecovered(
>   // Master::offer before we received AllocatorProcess::frameworkRemoved
>   // or AllocatorProcess::frameworkDeactivated, in which case we will
>   // have already recovered all of its resources).
> -  if (frameworks.contains(frameworkId) &&
> -      sorters[frameworks[frameworkId].role()]->contains(frameworkId.value())) {
> -    const std::string& role = frameworks[frameworkId].role();
> -    sorters[role]->unallocated(frameworkId.value(), resources);
> -    sorters[role]->remove(resources);
> -    roleSorter->unallocated(role, resources);
> +  if (frameworks.contains(frameworkId)) {
> +    const std::string& role = frameworks[frameworkId].role;
> +
> +    CHECK(sorters.contains(role));
> +
> +    if (sorters[role]->contains(frameworkId.value())) {
> +      sorters[role]->unallocated(frameworkId.value(), resources);
> +      sorters[role]->remove(resources);
> +      roleSorter->unallocated(role, resources);
> +    }
>   }
> 
>   // Update resources allocatable on slave (if slave still exists,
> @@ -779,11 +772,10 @@ HierarchicalAllocatorProcess<RoleSorter, FrameworkSorter>::isWhitelisted(
>     const SlaveID& slaveId)
> {
>   CHECK(initialized);
> -
>   CHECK(slaves.contains(slaveId));
> 
>   return whitelist.isNone() ||
> -         whitelist.get().contains(slaves[slaveId].hostname());
> +         whitelist.get().contains(slaves[slaveId].hostname);
> }
> 
> 
>