Apache Mesos
resources.hpp
Go to the documentation of this file.
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef __MESOS_V1_RESOURCES_HPP__
18 #define __MESOS_V1_RESOURCES_HPP__
19 
20 #include <map>
21 #include <iosfwd>
22 #include <set>
23 #include <string>
24 #include <vector>
25 
26 #include <google/protobuf/repeated_field.h>
27 
28 #include <mesos/v1/mesos.hpp>
29 #include <mesos/v1/values.hpp>
30 
31 #include <stout/bytes.hpp>
32 #include <stout/check.hpp>
33 #include <stout/error.hpp>
34 #include <stout/foreach.hpp>
35 #include <stout/hashmap.hpp>
36 #include <stout/json.hpp>
37 #include <stout/lambda.hpp>
38 #include <stout/nothing.hpp>
39 #include <stout/option.hpp>
40 #include <stout/try.hpp>
41 
42 
43 // Resources come in three types: scalar, ranges, and sets. These are
44 // represented using protocol buffers. To make manipulation of
45 // resources easier within the Mesos core and for scheduler writers,
46 // we provide generic overloaded operators (see below) as well as a
47 // general Resources class that encapsulates a collection of protocol
48 // buffer Resource objects. The Resources class also provides a few
49 // static routines to allow parsing resources (e.g., from the command
50 // line), as well as determining whether or not a Resource object is
51 // valid. Note that many of these operations have not been optimized
52 // but instead just written for correct semantics.
53 
54 namespace mesos {
55 namespace v1 {
56 
57 // Forward declaration.
58 class ResourceConversion;
59 
60 
61 // Helper functions.
62 bool operator==(
63  const Resource::ReservationInfo& left,
64  const Resource::ReservationInfo& right);
65 
66 
67 bool operator!=(
68  const Resource::ReservationInfo& left,
69  const Resource::ReservationInfo& right);
70 
71 
72 // NOTE: Resource objects stored in the class are always valid, are in
73 // the "post-reservation-refinement" format, and kept combined if possible.
74 // It is the caller's responsibility to validate any Resource object or
75 // repeated Resource protobufs before constructing a Resources object.
76 // Otherwise, invalid Resource objects will be silently stripped.
77 // Invalid Resource objects will also be silently ignored when used in
78 // arithmetic operations (e.g., +=, -=, etc.).
79 class Resources
80 {
81 private:
82  // An internal abstraction to facilitate managing shared resources.
83  // It allows 'Resources' to group identical shared resource objects
84  // together into a single 'Resource_' object and tracked by its internal
85  // counter. Non-shared resource objects are not grouped.
86  //
87  // The rest of the private section is below the public section. We
88  // need to define Resource_ first because the public typedefs below
89  // depend on it.
90  class Resource_
91  {
92  public:
93  /*implicit*/ Resource_(const Resource& _resource)
94  : resource(_resource),
95  sharedCount(None())
96  {
97  // Setting the counter to 1 to denote "one copy" of the shared resource.
98  if (resource.has_shared()) {
99  sharedCount = 1;
100  }
101  }
102 
103  // By implicitly converting to Resource we are able to keep Resource_
104  // logic internal and expose only the protobuf object.
105  operator const Resource&() const { return resource; }
106 
107  // Check whether this Resource_ object corresponds to a shared resource.
108  bool isShared() const { return sharedCount.isSome(); }
109 
110  // Validates this Resource_ object.
111  Option<Error> validate() const;
112 
113  // Check whether this Resource_ object is empty.
114  bool isEmpty() const;
115 
116  // The `Resource_` arithmetic, comparison operators and `contains()`
117  // method require the wrapped `resource` protobuf to have the same
118  // sharedness.
119  //
120  // For shared resources, the `resource` protobuf needs to be equal,
121  // and only the shared counters are adjusted or compared.
122  // For non-shared resources, the shared counters are none and the
123  // semantics of the Resource_ object's operators/contains() method
124  // are the same as those of the Resource objects.
125 
126  // Checks if this Resource_ is a superset of the given Resource_.
127  bool contains(const Resource_& that) const;
128 
129  // The arithmetic operators, viz. += and -= assume that the corresponding
130  // Resource objects are addable or subtractable already.
131  Resource_& operator+=(const Resource_& that);
132  Resource_& operator-=(const Resource_& that);
133 
134  bool operator==(const Resource_& that) const;
135  bool operator!=(const Resource_& that) const;
136 
137  // Friend classes and functions for access to private members.
138  friend class Resources;
139  friend std::ostream& operator<<(
140  std::ostream& stream, const Resource_& resource_);
141 
142  private:
143  // The protobuf Resource that is being managed.
144  Resource resource;
145 
146  // The counter for grouping shared 'resource' objects, None if the
147  // 'resource' is non-shared. This is an int so as to support arithmetic
148  // operations involving subtraction.
149  Option<int> sharedCount;
150  };
151 
152 public:
165  static Try<Resource> parse(
166  const std::string& name,
167  const std::string& value,
168  const std::string& role);
169 
184  static Try<Resources> parse(
185  const std::string& text,
186  const std::string& defaultRole = "*");
187 
208  const JSON::Array& resourcesJSON,
209  const std::string& defaultRole = "*");
210 
229  const std::string& text,
230  const std::string& defaultRole = "*");
231 
245  const std::string& text,
246  const std::string& defaultRole = "*");
247 
260  static Option<Error> validate(const Resource& resource);
261 
279  static Option<Error> validate(
280  const google::protobuf::RepeatedPtrField<Resource>& resources);
281 
282  // NOTE: The following predicate functions assume that the given resource is
283  // validated, and is in the "post-reservation-refinement" format. That is,
284  // the reservation state is represented by `Resource.reservations` field,
285  // and `Resource.role` and `Resource.reservation` fields are not set.
286  //
287  // See 'Resource Format' section in `mesos.proto` for more details.
288 
289  // Tests if the given Resource object is empty.
290  static bool isEmpty(const Resource& resource);
291 
292  // Tests if the given Resource object is a persistent volume.
293  static bool isPersistentVolume(const Resource& resource);
294 
295  // Tests if the given Resource object is a disk of the specified type.
296  static bool isDisk(
297  const Resource& resource,
299 
300  // Tests if the given Resource object is reserved. If the role is
301  // specified, tests that it's reserved for the given role.
302  static bool isReserved(
303  const Resource& resource,
304  const Option<std::string>& role = None());
305 
306  // Tests if the given Resource object is allocatable to the given role.
307  // A resource object is allocatable to 'role' if:
308  // * it is reserved to an ancestor of that role in the hierarchy, OR
309  // * it is reserved to 'role' itself, OR
310  // * it is unreserved.
311  static bool isAllocatableTo(
312  const Resource& resource,
313  const std::string& role);
314 
315  // Tests if the given Resource object is unreserved.
316  static bool isUnreserved(const Resource& resource);
317 
318  // Tests if the given Resource object is dynamically reserved.
319  static bool isDynamicallyReserved(const Resource& resource);
320 
321  // Tests if the given Resource object is revocable.
322  static bool isRevocable(const Resource& resource);
323 
324  // Tests if the given Resource object is shared.
325  static bool isShared(const Resource& resource);
326 
327  // Tests if the given Resources object is a "pure" scalar quantity which
328  // only consists of resource object with ONLY name, type (set to "Scalar")
329  // and scalar fields set.
330  static bool isScalarQuantity(const Resources& resources);
331 
332  // Tests if the given Resource object has refined reservations.
333  static bool hasRefinedReservations(const Resource& resource);
334 
335  // Tests if the given Resource object is provided by a resource provider.
336  static bool hasResourceProvider(const Resource& resource);
337 
338  // Returns the role to which the given Resource object is reserved for.
339  // This must be called only when the resource is reserved!
340  static const std::string& reservationRole(const Resource& resource);
341 
342  // Shrinks a scalar type `resource` to the target size.
343  // Returns true if the resource was shrunk to the target size,
344  // or the resource is already within the target size.
345  // Returns false otherwise (i.e. the resource is indivisible.
346  // E.g. MOUNT volume).
347  static bool shrink(Resource* resource, const Value::Scalar& target);
348 
349  // Returns the summed up Resources given a hashmap<Key, Resources>.
350  //
351  // NOTE: While scalar resources such as "cpus" sum correctly,
352  // non-scalar resources such as "ports" do not.
353  // e.g. "cpus:2" + "cpus:1" = "cpus:3"
354  // "ports:[0-100]" + "ports:[0-100]" = "ports:[0-100]"
355  //
356  // TODO(mpark): Deprecate this function once we introduce the
357  // concept of "cluster-wide" resources which provides correct
358  // semantics for summation over all types of resources. (e.g.
359  // non-scalar)
360  template <typename Key>
361  static Resources sum(const hashmap<Key, Resources>& _resources)
362  {
363  Resources result;
364 
365  foreachvalue (const Resources& resources, _resources) {
366  result += resources;
367  }
368 
369  return result;
370  }
371 
373 
374  // TODO(jieyu): Consider using C++11 initializer list.
375  /*implicit*/ Resources(const Resource& resource);
376 
377  /*implicit*/
378  Resources(const std::vector<Resource>& _resources);
379 
380  /*implicit*/
381  Resources(const google::protobuf::RepeatedPtrField<Resource>& _resources);
382 
383  Resources(const Resources& that) : resources(that.resources) {}
384 
386  {
387  if (this != &that) {
388  resources = that.resources;
389  }
390  return *this;
391  }
392 
393  bool empty() const { return resources.size() == 0; }
394 
395  size_t size() const { return resources.size(); }
396 
397  // Checks if this Resources is a superset of the given Resources.
398  bool contains(const Resources& that) const;
399 
400  // Checks if this Resources contains the given Resource.
401  bool contains(const Resource& that) const;
402 
403  // Count the Resource objects that match the specified value.
404  //
405  // NOTE:
406  // - For a non-shared resource the count can be at most 1 because all
407  // non-shared Resource objects in Resources are unique.
408  // - For a shared resource the count can be greater than 1.
409  // - If the resource is not in the Resources object, the count is 0.
410  size_t count(const Resource& that) const;
411 
412  // Allocates the resources to the given role (by setting the
413  // `AllocationInfo.role`). Any existing allocation will be
414  // over-written.
415  void allocate(const std::string& role);
416 
417  // Unallocates the resources.
418  void unallocate();
419 
420  // Filter resources based on the given predicate.
422  const lambda::function<bool(const Resource&)>& predicate) const;
423 
424  // Returns the reserved resources, by role.
426 
427  // Returns the reserved resources for the role, if specified.
428  // Note that the "*" role represents unreserved resources,
429  // and will be ignored.
430  Resources reserved(const Option<std::string>& role = None()) const;
431 
432  // Returns resources allocatable to role. See `isAllocatableTo` for the
433  // definition of 'allocatableTo'.
434  Resources allocatableTo(const std::string& role) const;
435 
436  // Returns the unreserved resources.
437  Resources unreserved() const;
438 
439  // Returns the persistent volumes.
441 
442  // Returns the revocable resources.
443  Resources revocable() const;
444 
445  // Returns the non-revocable resources, effectively !revocable().
446  Resources nonRevocable() const;
447 
448  // Returns the shared resources.
449  Resources shared() const;
450 
451  // Returns the non-shared resources.
452  Resources nonShared() const;
453 
454  // Returns the per-role allocations within these resource objects.
455  // This must be called only when the resources are allocated!
457 
458  // Returns a `Resources` object with the new reservation added to the back.
459  // The new reservation must be a valid refinement of the current reservation.
460  Resources pushReservation(const Resource::ReservationInfo& reservation) const;
461 
462  // Returns a `Resources` object with the last reservation removed.
463  // Every resource in `Resources` must have `resource.reservations_size() > 0`.
464  Resources popReservation() const;
465 
466  // Returns a `Resources` object with all of the reservations removed.
467  Resources toUnreserved() const;
468 
469  // Returns a Resources object that contains all the scalar resources
470  // but with all the meta-data fields, such as AllocationInfo,
471  // ReservationInfo and etc. cleared. Only scalar resources' name,
472  // type (SCALAR) and value are preserved.
473  //
474  // This is intended for code that would like to aggregate together
475  // Resource values without regard for metadata like whether the
476  // resource is reserved or the particular volume ID in use. For
477  // example, when calculating the total resources in a cluster,
478  // preserving such information has a major performance cost.
480 
481  // Finds a Resources object with the same amount of each resource
482  // type as "targets" from these Resources. The roles specified in
483  // "targets" set the preference order. For each resource type,
484  // resources are first taken from the specified role, then from '*',
485  // then from any other role.
486  // TODO(jieyu): 'find' contains some allocation logic for scalars and
487  // fixed set / range elements. However, this is not sufficient for
488  // schedulers that want, say, any N available ports. We should
489  // consider moving this to an internal "allocation" library for our
490  // example frameworks to leverage.
491  Option<Resources> find(const Resources& targets) const;
492 
493  // Applies a resource conversion by taking out the `consumed`
494  // resources and adding back the `converted` resources. Returns an
495  // Error if the conversion cannot be applied.
496  Try<Resources> apply(const ResourceConversion& conversion) const;
497 
498  // Obtains the conversion from the given operation and applies the
499  // conversion. This method serves a syntax sugar for applying a
500  // resource conversion.
501  // TODO(jieyu): Consider remove this method once we updated all the
502  // call sites.
503  Try<Resources> apply(const Offer::Operation& operation) const;
504 
505  template <typename Iterable>
506  Try<Resources> apply(const Iterable& iterable) const
507  {
508  Resources result = *this;
509 
510  foreach (const auto& t, iterable) {
511  Try<Resources> converted = result.apply(t);
512  if (converted.isError()) {
513  return Error(converted.error());
514  }
515 
516  result = converted.get();
517  }
518 
519  return result;
520  }
521 
522  // Helpers to get resource values. We consider all roles here.
523  template <typename T>
524  Option<T> get(const std::string& name) const;
525 
526  // Get resources of the given name.
527  Resources get(const std::string& name) const;
528 
529  // Get all the resources that are scalars.
530  Resources scalars() const;
531 
532  // Get the set of unique resource names.
533  std::set<std::string> names() const;
534 
535  // Get the types of resources associated with each resource name.
536  // NOTE: Resources of the same name must have the same type, as
537  // enforced by Resources::parse().
538  std::map<std::string, Value_Type> types() const;
539 
540  // Helpers to get known resource types.
541  // TODO(vinod): Fix this when we make these types as first class
542  // protobufs.
543  Option<double> cpus() const;
544  Option<double> gpus() const;
545  Option<Bytes> mem() const;
546  Option<Bytes> disk() const;
547 
548  // TODO(vinod): Provide a Ranges abstraction.
550 
551  // TODO(jieyu): Consider returning an EphemeralPorts abstraction
552  // which holds the ephemeral ports allocation logic.
554 
555  // NOTE: Non-`const` `iterator`, `begin()` and `end()` are __intentionally__
556  // defined with `const` semantics in order to prevent mutable access to the
557  // `Resource` objects within `resources`.
558  typedef std::vector<Resource_>::const_iterator iterator;
559  typedef std::vector<Resource_>::const_iterator const_iterator;
560 
561  const_iterator begin()
562  {
563  return static_cast<const std::vector<Resource_>&>(resources).begin();
564  }
565 
566  const_iterator end()
567  {
568  return static_cast<const std::vector<Resource_>&>(resources).end();
569  }
570 
571  const_iterator begin() const { return resources.begin(); }
572  const_iterator end() const { return resources.end(); }
573 
574  // Using this operator makes it easy to copy a resources object into
575  // a protocol buffer field.
576  // Note that the google::protobuf::RepeatedPtrField<Resource> is
577  // generated at runtime.
578  operator google::protobuf::RepeatedPtrField<Resource>() const;
579 
580  bool operator==(const Resources& that) const;
581  bool operator!=(const Resources& that) const;
582 
583  // NOTE: If any error occurs (e.g., input Resource is not valid or
584  // the first operand is not a superset of the second operand while
585  // doing subtraction), the semantics is as though the second operand
586  // was actually just an empty resource (as though you didn't do the
587  // operation at all).
588  Resources operator+(const Resource& that) const;
589  Resources operator+(const Resources& that) const;
590  Resources& operator+=(const Resource& that);
591  Resources& operator+=(const Resources& that);
592 
593  Resources operator-(const Resource& that) const;
594  Resources operator-(const Resources& that) const;
595  Resources& operator-=(const Resource& that);
596  Resources& operator-=(const Resources& that);
597 
598  friend std::ostream& operator<<(
599  std::ostream& stream, const Resource_& resource_);
600 
601 private:
602  // Similar to 'contains(const Resource&)' but skips the validity
603  // check. This can be used to avoid the performance overhead of
604  // calling 'contains(const Resource&)' when the resource can be
605  // assumed valid (e.g. it's inside a Resources).
606  //
607  // TODO(jieyu): Measure performance overhead of validity check to
608  // ensure this is warranted.
609  bool _contains(const Resource_& that) const;
610 
611  // Similar to the public 'find', but only for a single Resource
612  // object. The target resource may span multiple roles, so this
613  // returns Resources.
614  Option<Resources> find(const Resource& target) const;
615 
616  // Validation-free versions of += and -= `Resource_` operators.
617  // These can be used when `r` is already validated.
618  //
619  // NOTE: `Resource` objects are implicitly converted to `Resource_`
620  // objects, so here the API can also accept a `Resource` object.
621  void add(const Resource_& r);
622  void subtract(const Resource_& r);
623 
624  Resources operator+(const Resource_& that) const;
625  Resources& operator+=(const Resource_& that);
626 
627  Resources operator-(const Resource_& that) const;
628  Resources& operator-=(const Resource_& that);
629 
630  std::vector<Resource_> resources;
631 };
632 
633 
634 std::ostream& operator<<(
635  std::ostream& stream,
636  const Resources::Resource_& resource);
637 
638 
639 std::ostream& operator<<(std::ostream& stream, const Resource& resource);
640 
641 
642 std::ostream& operator<<(std::ostream& stream, const Resources& resources);
643 
644 
645 std::ostream& operator<<(
646  std::ostream& stream,
647  const google::protobuf::RepeatedPtrField<Resource>& resources);
648 
649 
651  const google::protobuf::RepeatedPtrField<Resource>& left,
652  const Resources& right)
653 {
654  return Resources(left) + right;
655 }
656 
657 
659  const google::protobuf::RepeatedPtrField<Resource>& left,
660  const Resources& right)
661 {
662  return Resources(left) - right;
663 }
664 
665 
666 inline bool operator==(
667  const google::protobuf::RepeatedPtrField<Resource>& left,
668  const Resources& right)
669 {
670  return Resources(left) == right;
671 }
672 
673 
674 template <typename Key>
677  const hashmap<Key, Resources>& right)
678 {
679  foreachpair (const Key& key, const Resources& resources, right) {
680  left[key] += resources;
681  }
682  return left;
683 }
684 
685 
686 template <typename Key>
688  const hashmap<Key, Resources>& left,
689  const hashmap<Key, Resources>& right)
690 {
691  hashmap<Key, Resources> result = left;
692  result += right;
693  return result;
694 }
695 
696 
702 {
703 public:
704  typedef lambda::function<Try<Nothing>(const Resources&)> PostValidation;
705 
707  const Resources& _consumed,
708  const Resources& _converted,
709  const Option<PostValidation>& _postValidation = None())
710  : consumed(_consumed),
711  converted(_converted),
712  postValidation(_postValidation) {}
713 
714  Try<Resources> apply(const Resources& resources) const;
715 
719 };
720 
721 } // namespace v1 {
722 } // namespace mesos {
723 
724 #endif // __MESOS_V1_RESOURCES_HPP__
Resources toUnreserved() const
Resources revocable() const
Resources reserved(const Option< std::string > &role=None()) const
Resources & operator=(const Resources &that)
Definition: resources.hpp:385
static Option< Error > validate(const Resource &resource)
Validates a Resource object.
Definition: errorbase.hpp:36
Resources unreserved() const
T & get()&
Definition: try.hpp:73
const_iterator end()
Definition: resources.hpp:566
static bool isPersistentVolume(const Resource &resource)
Definition: check.hpp:33
Option< Bytes > disk() const
Resources nonRevocable() const
Option< double > cpus() const
Try< Resources > apply(const Iterable &iterable) const
Definition: resources.hpp:506
static Try< std::vector< Resource > > fromJSON(const JSON::Array &resourcesJSON, const std::string &defaultRole="*")
Parses an input JSON array into a vector of Resource objects.
static bool isScalarQuantity(const Resources &resources)
Resources popReservation() const
Resources persistentVolumes() const
static Try< std::vector< Resource > > fromSimpleString(const std::string &text, const std::string &defaultRole="*")
Parses an input text string into a vector of Resource objects.
bool empty() const
Definition: resources.hpp:393
Resources(const Resources &that)
Definition: resources.hpp:383
static bool isAllocatableTo(const Resource &resource, const std::string &role)
bool operator==(const Resources &that) const
static const std::string & reservationRole(const Resource &resource)
Definition: json.hpp:198
Resources filter(const lambda::function< bool(const Resource &)> &predicate) const
static bool hasResourceProvider(const Resource &resource)
Operation
Definition: cgroups.hpp:441
Future< Nothing > add(const T &metric)
Definition: metrics.hpp:95
Resources & operator-=(const Resource &that)
static bool isDynamicallyReserved(const Resource &resource)
std::map< std::string, Value_Type > types() const
static Try< Resource > parse(const std::string &name, const std::string &value, const std::string &role)
Returns a Resource with the given name, value, and role.
static bool hasRefinedReservations(const Resource &resource)
static bool isReserved(const Resource &resource, const Option< std::string > &role=None())
hashmap< std::string, Resources > allocations() const
Definition: hashmap.hpp:38
Resources pushReservation(const Resource::ReservationInfo &reservation) const
Represents a resource conversion, usually as a result of an offer operation.
Definition: resources.hpp:701
const_iterator begin() const
Definition: resources.hpp:571
Resources createStrippedScalarQuantity() const
size_t size() const
Definition: resources.hpp:395
bool contains(const Resources &that) const
hashmap< std::string, Resources > reservations() const
Resources nonShared() const
static bool isShared(const Resource &resource)
Resources operator-(const Resource &that) const
std::vector< Resource_ >::const_iterator const_iterator
Definition: resources.hpp:559
Resources consumed
Definition: resources.hpp:716
ResourceConversion(const Resources &_consumed, const Resources &_converted, const Option< PostValidation > &_postValidation=None())
Definition: resources.hpp:706
Definition: spec.hpp:30
void allocate(const std::string &role)
const_iterator end() const
Definition: resources.hpp:572
Definition: resources.hpp:79
#define foreachpair(KEY, VALUE, ELEMS)
Definition: foreach.hpp:51
bool operator==(const CommandInfo &left, const CommandInfo &right)
#define foreachvalue(VALUE, ELEMS)
Definition: foreach.hpp:77
Option< Value::Ranges > ports() const
Resources()
Definition: resources.hpp:372
friend std::ostream & operator<<(std::ostream &stream, const Resource_ &resource_)
static Try error(const E &e)
Definition: try.hpp:42
lambda::function< Try< Nothing >const Resources &)> PostValidation
Definition: resources.hpp:704
const_iterator begin()
Definition: resources.hpp:561
size_t count(const Resource &that) const
Definition: none.hpp:27
bool isError() const
Definition: try.hpp:71
Option< Bytes > mem() const
bool operator!=(const Resources &that) const
static bool isRevocable(const Resource &resource)
Type
Definition: capabilities.hpp:79
Resources scalars() const
Resources converted
Definition: resources.hpp:717
Resources allocatableTo(const std::string &role) const
std::vector< Resource_ >::const_iterator iterator
Definition: resources.hpp:558
static bool isUnreserved(const Resource &resource)
Try< uint32_t > type(const std::string &path)
Option< Value::Ranges > ephemeral_ports() const
static Try< std::vector< Resource > > fromString(const std::string &text, const std::string &defaultRole="*")
Parse an input string into a vector of Resource objects.
Resources operator+(const Resource &that) const
bool operator!=(const Labels &left, const Labels &right)
Try< Resources > apply(const ResourceConversion &conversion) const
static bool isDisk(const Resource &resource, const Resource::DiskInfo::Source::Type &type)
std::set< std::string > names() const
static bool shrink(Resource *resource, const Value::Scalar &target)
static Resources sum(const hashmap< Key, Resources > &_resources)
Definition: resources.hpp:361
constexpr const char * name
Definition: shell.hpp:43
Option< Resources > find(const Resources &targets) const
Resources shared() const
Resources & operator+=(const Resource &that)
Option< double > gpus() const
Option< PostValidation > postValidation
Definition: resources.hpp:718
static bool isEmpty(const Resource &resource)