| 381 | } |
| 382 | |
| 383 | Errata |
| 384 | VolumeAllocator::allocateFor(Span &span) |
| 385 | { |
| 386 | Errata zret; |
| 387 | |
| 388 | /// Scaling factor for shares, effectively the accuracy. |
| 389 | static const int64_t SCALE = 1000; |
| 390 | int64_t total_shares = 0; |
| 391 | |
| 392 | if (Verbosity >= NORMAL) { |
| 393 | std::cout << "Allocating " << CacheStripeBlocks(round_down(span._len)).count() << " stripe blocks from span " |
| 394 | << span._path.string() << std::endl; |
| 395 | } |
| 396 | |
| 397 | // Walk the volumes and get the relative allocations. |
| 398 | for (auto &v : _av) { |
| 399 | auto delta = v._config._alloc - v._size; |
| 400 | if (delta > 0) { |
| 401 | v._deficit = (delta.count() * SCALE) / v._config._alloc.count(); |
| 402 | v._shares = delta.count() * v._deficit; |
| 403 | total_shares += v._shares; |
| 404 | } else { |
| 405 | v._shares = 0; |
| 406 | } |
| 407 | } |
| 408 | assert(total_shares != 0); |
| 409 | // Now allocate blocks. |
| 410 | CacheStripeBlocks span_blocks(round_down(span._free_space)); |
| 411 | CacheStripeBlocks span_used{0}; |
| 412 | |
| 413 | // sort by deficit so least relatively full volumes go first. |
| 414 | std::sort(_av.begin(), _av.end(), [](V const &lhs, V const &rhs) { return lhs._deficit > rhs._deficit; }); |
| 415 | for (auto &v : _av) { |
| 416 | if (v._shares) { |
| 417 | CacheStripeBlocks n{(((span_blocks - span_used).count() * v._shares) + total_shares - 1) / total_shares}; |
| 418 | CacheStripeBlocks delta{v._config._alloc - v._size}; |
| 419 | // Not sure why this is needed. But a large and empty volume can dominate the shares |
| 420 | // enough to get more than it actually needs if the other volume are relative small or full. |
| 421 | // I need to do more math to see if the weighting can be adjusted to not have this happen. |
| 422 | n = std::min(n, delta); |
| 423 | v._size += n; |
| 424 | span_used += n; |
| 425 | total_shares -= v._shares; |
| 426 | Errata z = _cache.allocStripe(&span, v._config._idx, round_up(n)); |
| 427 | if (Verbosity >= NORMAL) { |
| 428 | std::cout << " " << n << " to volume " << v._config._idx << std::endl; |
| 429 | } |
| 430 | if (!z) { |
| 431 | std::cout << z; |
| 432 | } |
| 433 | } |
| 434 | } |
| 435 | if (Verbosity >= NORMAL) { |
| 436 | std::cout << " Total " << span_used << std::endl; |
| 437 | } |
| 438 | if (OPEN_RW_FLAG) { |
| 439 | if (Verbosity >= NORMAL) { |
| 440 | std::cout << " Updating Header ... "; |
no test coverage detected