Tests if we can subtract "right" from "left" resulting in one valid Resource object. For example, two Resource objects with different name, type or role are not subtractable. NOTE: Set subtraction is always well defined, it does not require 'right' to be contained within 'left'. For example, assuming that "left = {1, 2}" and "right = {2, 3}", "left" and "right" are subtractable because "left - rig
| 465 | // subtractable because "left - right = {1}". However, "left" does not |
| 466 | // contain "right". |
| 467 | static bool subtractable(const Resource& left, const Resource& right) |
| 468 | { |
| 469 | // Check SharedInfo. |
| 470 | if (left.has_shared() != right.has_shared()) { |
| 471 | return false; |
| 472 | } |
| 473 | |
| 474 | // For shared resources, they can be subtracted only if left == right. |
| 475 | if (left.has_shared()) { |
| 476 | return left == right; |
| 477 | } |
| 478 | |
| 479 | // Now, we verify if the two non-shared resources can be subtracted. |
| 480 | if (left.name() != right.name() || left.type() != right.type()) { |
| 481 | return false; |
| 482 | } |
| 483 | |
| 484 | // Check AllocationInfo. |
| 485 | if (left.has_allocation_info() != right.has_allocation_info()) { |
| 486 | return false; |
| 487 | } |
| 488 | |
| 489 | if (left.has_allocation_info() && |
| 490 | left.allocation_info() != right.allocation_info()) { |
| 491 | return false; |
| 492 | } |
| 493 | |
| 494 | // Check the stack of ReservationInfo. |
| 495 | if (left.reservations_size() != right.reservations_size()) { |
| 496 | return false; |
| 497 | } |
| 498 | |
| 499 | for (int i = 0; i < left.reservations_size(); ++i) { |
| 500 | if (left.reservations(i) != right.reservations(i)) { |
| 501 | return false; |
| 502 | } |
| 503 | } |
| 504 | |
| 505 | // Check DiskInfo. |
| 506 | if (left.has_disk() != right.has_disk()) { return false; } |
| 507 | |
| 508 | if (left.has_disk()) { |
| 509 | if (left.disk() != right.disk()) { return false; } |
| 510 | |
| 511 | if (left.disk().has_source()) { |
| 512 | switch (left.disk().source().type()) { |
| 513 | case Resource::DiskInfo::Source::PATH: { |
| 514 | // Two PATH resources can be subtracted if their disks are identical. |
| 515 | break; |
| 516 | } |
| 517 | case Resource::DiskInfo::Source::BLOCK: |
| 518 | case Resource::DiskInfo::Source::MOUNT: { |
| 519 | // Two resources that represent exclusive 'MOUNT' or 'BLOCK' disks |
| 520 | // cannot be subtracted from each other if they are not the exact same |
| 521 | // mount; this would defeat the exclusivity. |
| 522 | if (left != right) { |
| 523 | return false; |
| 524 | } |