| 1516 | } |
| 1517 | |
| 1518 | Status TmpFileGroup::AllocateLocalSpace(int64_t num_bytes, TmpFile** tmp_file, |
| 1519 | int64_t* file_offset, vector<int>* at_capacity_dirs, bool* alloc_full) { |
| 1520 | int64_t scratch_range_bytes = |
| 1521 | RoundUpToScratchRangeSize(tmp_file_mgr_->punch_holes(), num_bytes); |
| 1522 | int free_ranges_idx = BitUtil::Log2Ceiling64(scratch_range_bytes); |
| 1523 | if (!free_ranges_[free_ranges_idx].empty()) { |
| 1524 | DCHECK(!tmp_file_mgr_->punch_holes()) << "Ranges not recycled when punching holes"; |
| 1525 | *tmp_file = free_ranges_[free_ranges_idx].back().first; |
| 1526 | *file_offset = free_ranges_[free_ranges_idx].back().second; |
| 1527 | free_ranges_[free_ranges_idx].pop_back(); |
| 1528 | return Status::OK(); |
| 1529 | } |
| 1530 | |
| 1531 | if (bytes_limit_ != -1 |
| 1532 | && current_bytes_allocated_.Load() + scratch_range_bytes > bytes_limit_) { |
| 1533 | return Status(TErrorCode::SCRATCH_LIMIT_EXCEEDED, bytes_limit_, GetBackendString()); |
| 1534 | } |
| 1535 | |
| 1536 | // Lazily create the files on the first write. |
| 1537 | if (tmp_files_.empty()) RETURN_IF_ERROR(CreateFiles()); |
| 1538 | |
| 1539 | // Find the next physical file in priority based round-robin order and allocate a range |
| 1540 | // from it. |
| 1541 | for (const auto& entry: tmp_files_index_range_) { |
| 1542 | const int priority = entry.first; |
| 1543 | const int start = entry.second.start; |
| 1544 | const int end = entry.second.end; |
| 1545 | DCHECK (0 <= start && start <= end && end < tmp_files_.size()) |
| 1546 | << "Invalid index range: [" << start << ", " << end << "] " |
| 1547 | << "tmp_files_.size(): " << tmp_files_.size(); |
| 1548 | for (int index = start; index <= end; ++index) { |
| 1549 | const int idx = next_allocation_index_[priority]; |
| 1550 | next_allocation_index_[priority] = start + (idx - start + 1) % (end - start + 1); |
| 1551 | *tmp_file = tmp_files_[idx].get(); |
| 1552 | if ((*tmp_file)->is_blacklisted()) continue; |
| 1553 | // Check the per-directory limit. |
| 1554 | if (!(*tmp_file)->AllocateSpace(scratch_range_bytes, file_offset)) { |
| 1555 | at_capacity_dirs->push_back(idx); |
| 1556 | continue; |
| 1557 | } |
| 1558 | UpdateScratchSpaceMetrics(scratch_range_bytes); |
| 1559 | return Status::OK(); |
| 1560 | } |
| 1561 | } |
| 1562 | |
| 1563 | // Using a bool to notify there is no more space left, could cost less overhead than |
| 1564 | // using a Status, because we want the error reporting as fast as possible for the |
| 1565 | // case of mixing use of remote and local scratch space, so that it can keep trying to |
| 1566 | // allocate from the remote after this. |
| 1567 | *alloc_full = true; |
| 1568 | return Status::OK(); |
| 1569 | } |
| 1570 | |
| 1571 | Status TmpFileGroup::AllocateSpace( |
| 1572 | int64_t num_bytes, TmpFile** tmp_file, int64_t* file_offset) { |
nothing calls this directly
no test coverage detected