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