Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : * Copyright Contributors to the OpenSDN project 4 : */ 5 : 6 : #include "base/label_block.h" 7 : 8 : #include <stdio.h> 9 : 10 : #include <cassert> 11 : #include <string> 12 : 13 : using std::string; 14 : 15 10052 : LabelBlockManager::LabelBlockManager() { 16 10052 : refcount_ = 0; 17 10052 : } 18 : 19 10052 : LabelBlockManager::~LabelBlockManager() { 20 10052 : assert(blocks_.size() == 0); 21 10052 : } 22 : 23 1791 : LabelBlockPtr LabelBlockManager::LocateBlock(uint32_t first, uint32_t last) { 24 1791 : std::scoped_lock lock(mutex_); 25 : 26 1792 : for (LabelBlockList::iterator it = blocks_.begin(); 27 1975 : it != blocks_.end(); ++it) { 28 476 : LabelBlock *block = *it; 29 476 : if (block->first_ == first && block->last_ == last) { 30 293 : return LabelBlockPtr(block); 31 : } 32 : } 33 : 34 1499 : LabelBlock *block = new LabelBlock(this, first, last); 35 1499 : blocks_.push_back(block); 36 1498 : return LabelBlockPtr(block); 37 1792 : } 38 : 39 1499 : void LabelBlockManager::RemoveBlock(LabelBlock *block) { 40 1499 : for (LabelBlockList::iterator it = blocks_.begin(); 41 1590 : it != blocks_.end(); ++it) { 42 1590 : if (*it == block) { 43 1499 : blocks_.erase(it); 44 1499 : return; 45 : } 46 : } 47 0 : assert(false); 48 : } 49 : 50 1067 : size_t LabelBlockManager::size() { 51 1067 : std::scoped_lock lock(mutex_); 52 2134 : return blocks_.size(); 53 1067 : } 54 : 55 6426 : LabelBlock::LabelBlock(uint32_t first, uint32_t last) 56 6426 : : block_manager_(NULL), 57 6426 : first_(first), 58 6426 : last_(last), 59 6426 : prev_pos_(BitSet::npos) { 60 6426 : refcount_ = 0; 61 6427 : } 62 : 63 1499 : LabelBlock::LabelBlock( 64 1499 : LabelBlockManager *block_manager, uint32_t first, uint32_t last) 65 1499 : : block_manager_(block_manager), 66 1499 : first_(first), 67 1499 : last_(last), 68 1499 : prev_pos_(BitSet::npos) { 69 1499 : refcount_ = 0; 70 1499 : } 71 : 72 7926 : LabelBlock::~LabelBlock() { 73 7926 : assert(used_bitset_.empty()); 74 7926 : if (block_manager_) 75 1499 : block_manager_->RemoveBlock(this); 76 7926 : } 77 : 78 5515 : uint32_t LabelBlock::AllocateLabel() { 79 5515 : std::scoped_lock lock(mutex_); 80 : 81 : size_t pos; 82 6043 : for (int idx = 0; idx < 2; prev_pos_ = BitSet::npos, idx++) { 83 6033 : if (prev_pos_ == BitSet::npos) { 84 2126 : pos = used_bitset_.find_first_clear(); 85 : } else { 86 3907 : pos = used_bitset_.find_next_clear(prev_pos_); 87 : } 88 : 89 6033 : if (first_ + pos <= last_) { 90 5505 : used_bitset_.set(pos); 91 5505 : prev_pos_ = pos; 92 5505 : return static_cast<uint32_t>(first_ + pos); 93 : } 94 : } 95 : 96 10 : return 0; 97 5515 : } 98 : 99 5505 : void LabelBlock::ReleaseLabel(uint32_t value) { 100 5505 : std::scoped_lock lock(mutex_); 101 : 102 5505 : assert(value >= first_ && value <= last_); 103 5505 : size_t pos = value - first_; 104 5505 : used_bitset_.reset(pos); 105 5505 : } 106 : 107 8 : string LabelBlock::ToString() const { 108 : char repr[32]; 109 8 : snprintf(repr, sizeof(repr), "%u-%u", first_, last_); 110 8 : return repr; 111 : }