paul@6 | 1 | #include "access_map.h" |
paul@6 | 2 | |
paul@6 | 3 | /* Return the flexpage supporting 'position'. */ |
paul@6 | 4 | |
paul@6 | 5 | Flexpage *AccessMap::find(offset_t position) |
paul@6 | 6 | { |
paul@6 | 7 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 8 | |
paul@6 | 9 | _AccessMap::iterator it = _flexpages.upper_bound(position); |
paul@6 | 10 | |
paul@6 | 11 | if ((_flexpages.size() > 0) && (it != _flexpages.begin())) |
paul@6 | 12 | { |
paul@6 | 13 | it--; |
paul@6 | 14 | |
paul@6 | 15 | if (it->second->supports_position(position)) |
paul@6 | 16 | return it->second; |
paul@6 | 17 | } |
paul@6 | 18 | |
paul@6 | 19 | return NULL; |
paul@6 | 20 | } |
paul@6 | 21 | |
paul@6 | 22 | /* Insert a mapping for 'flexpage'. */ |
paul@6 | 23 | |
paul@6 | 24 | void AccessMap::insert(Flexpage *flexpage) |
paul@6 | 25 | { |
paul@6 | 26 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 27 | |
paul@6 | 28 | _flexpages.insert(_AccessMapEntry(flexpage->base_offset, flexpage)); |
paul@6 | 29 | } |
paul@6 | 30 | |
paul@6 | 31 | /* Remove the mapping supported by 'flexpage'. |
paul@6 | 32 | |
paul@6 | 33 | The flexpage may have obtained by another mapper before being purged from |
paul@6 | 34 | this object's mapping and before being purged from the queue (and thus |
paul@6 | 35 | disassociated from this mapper), leaving an opportunity for another mapper to |
paul@6 | 36 | now be removing it here. In such a situation, flushing has already occurred |
paul@6 | 37 | and will not be performed again. */ |
paul@6 | 38 | |
paul@6 | 39 | bool AccessMap::remove(PageOwner *owner, Flexpage *flexpage) |
paul@6 | 40 | { |
paul@6 | 41 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 42 | |
paul@6 | 43 | _AccessMap::iterator it = _flexpages.find(flexpage->base_offset); |
paul@6 | 44 | |
paul@6 | 45 | if (it != _flexpages.end()) |
paul@6 | 46 | { |
paul@6 | 47 | owner->flush(flexpage, true); |
paul@6 | 48 | _flexpages.erase(flexpage->base_offset); |
paul@6 | 49 | return true; |
paul@6 | 50 | } |
paul@6 | 51 | |
paul@6 | 52 | return false; |
paul@6 | 53 | } |
paul@6 | 54 | |
paul@6 | 55 | /* Purge all flexpages, using the 'owner' to flush their contents and |
paul@6 | 56 | 'pages' to make the flexpages available to other accessors. */ |
paul@6 | 57 | |
paul@6 | 58 | void AccessMap::purge(PageOwner *owner, Pages *pages) |
paul@6 | 59 | { |
paul@6 | 60 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 61 | |
paul@6 | 62 | _AccessMap::iterator it = _flexpages.begin(), entry; |
paul@6 | 63 | |
paul@6 | 64 | while (it != _flexpages.end()) |
paul@6 | 65 | { |
paul@6 | 66 | entry = it; |
paul@6 | 67 | it++; |
paul@6 | 68 | |
paul@6 | 69 | Flexpage *flexpage = entry->second; |
paul@6 | 70 | |
paul@6 | 71 | /* Some flexpages may be unavailable in the queue. Only those |
paul@6 | 72 | that can be reserved should be flushed and made available |
paul@6 | 73 | again. */ |
paul@6 | 74 | |
paul@6 | 75 | if (pages->reserve(owner, flexpage)) |
paul@6 | 76 | { |
paul@6 | 77 | owner->flush(flexpage, true); |
paul@6 | 78 | pages->release(flexpage); |
paul@6 | 79 | _flexpages.erase(entry); |
paul@6 | 80 | } |
paul@6 | 81 | } |
paul@6 | 82 | } |
paul@6 | 83 | |
paul@6 | 84 | /* Flush flexpages in the given range from 'start' with 'size', using 'owner' |
paul@6 | 85 | and 'pages'. */ |
paul@6 | 86 | |
paul@6 | 87 | void AccessMap::flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages) |
paul@6 | 88 | { |
paul@6 | 89 | offset_t end = start + size; |
paul@6 | 90 | |
paul@6 | 91 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 92 | |
paul@6 | 93 | /* The start may be within an existing flexpage where the flexpage size is a |
paul@6 | 94 | page multiple. */ |
paul@6 | 95 | |
paul@6 | 96 | _AccessMap::iterator it = _flexpages.upper_bound(start), entry; |
paul@6 | 97 | |
paul@6 | 98 | if ((_flexpages.size() > 0) && (it != _flexpages.begin())) |
paul@6 | 99 | it--; |
paul@6 | 100 | |
paul@6 | 101 | /* Inspect flexpages at or after start until end. */ |
paul@6 | 102 | |
paul@6 | 103 | while (it != _flexpages.end()) |
paul@6 | 104 | { |
paul@6 | 105 | entry = it; |
paul@6 | 106 | it++; |
paul@6 | 107 | |
paul@6 | 108 | Flexpage *flexpage = entry->second; |
paul@6 | 109 | |
paul@6 | 110 | if (flexpage->base_offset >= end) |
paul@6 | 111 | break; |
paul@6 | 112 | |
paul@6 | 113 | /* Attempt to flush each flexpage, releasing ones that are no longer |
paul@6 | 114 | needed. */ |
paul@6 | 115 | |
paul@6 | 116 | if (pages->reserve(owner, flexpage)) |
paul@6 | 117 | { |
paul@6 | 118 | owner->flush(flexpage, false); |
paul@6 | 119 | |
paul@6 | 120 | /* Where no users of the flexpage persist, release the flexpage for |
paul@6 | 121 | reuse and remove this entry. */ |
paul@6 | 122 | |
paul@6 | 123 | if (!flexpage->valid()) |
paul@6 | 124 | { |
paul@6 | 125 | pages->release(flexpage); |
paul@6 | 126 | _flexpages.erase(entry); |
paul@6 | 127 | } |
paul@6 | 128 | else |
paul@6 | 129 | pages->queue(owner, flexpage); |
paul@6 | 130 | } |
paul@6 | 131 | } |
paul@6 | 132 | } |
paul@6 | 133 | |
paul@6 | 134 | // vim: tabstop=4 expandtab shiftwidth=4 |