1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/access_map.cc Sat Jan 23 00:01:22 2021 +0100
1.3 @@ -0,0 +1,134 @@
1.4 +#include "access_map.h"
1.5 +
1.6 +/* Return the flexpage supporting 'position'. */
1.7 +
1.8 +Flexpage *AccessMap::find(offset_t position)
1.9 +{
1.10 + std::lock_guard<std::mutex> guard(_lock);
1.11 +
1.12 + _AccessMap::iterator it = _flexpages.upper_bound(position);
1.13 +
1.14 + if ((_flexpages.size() > 0) && (it != _flexpages.begin()))
1.15 + {
1.16 + it--;
1.17 +
1.18 + if (it->second->supports_position(position))
1.19 + return it->second;
1.20 + }
1.21 +
1.22 + return NULL;
1.23 +}
1.24 +
1.25 +/* Insert a mapping for 'flexpage'. */
1.26 +
1.27 +void AccessMap::insert(Flexpage *flexpage)
1.28 +{
1.29 + std::lock_guard<std::mutex> guard(_lock);
1.30 +
1.31 + _flexpages.insert(_AccessMapEntry(flexpage->base_offset, flexpage));
1.32 +}
1.33 +
1.34 +/* Remove the mapping supported by 'flexpage'.
1.35 +
1.36 + The flexpage may have obtained by another mapper before being purged from
1.37 + this object's mapping and before being purged from the queue (and thus
1.38 + disassociated from this mapper), leaving an opportunity for another mapper to
1.39 + now be removing it here. In such a situation, flushing has already occurred
1.40 + and will not be performed again. */
1.41 +
1.42 +bool AccessMap::remove(PageOwner *owner, Flexpage *flexpage)
1.43 +{
1.44 + std::lock_guard<std::mutex> guard(_lock);
1.45 +
1.46 + _AccessMap::iterator it = _flexpages.find(flexpage->base_offset);
1.47 +
1.48 + if (it != _flexpages.end())
1.49 + {
1.50 + owner->flush(flexpage, true);
1.51 + _flexpages.erase(flexpage->base_offset);
1.52 + return true;
1.53 + }
1.54 +
1.55 + return false;
1.56 +}
1.57 +
1.58 +/* Purge all flexpages, using the 'owner' to flush their contents and
1.59 + 'pages' to make the flexpages available to other accessors. */
1.60 +
1.61 +void AccessMap::purge(PageOwner *owner, Pages *pages)
1.62 +{
1.63 + std::lock_guard<std::mutex> guard(_lock);
1.64 +
1.65 + _AccessMap::iterator it = _flexpages.begin(), entry;
1.66 +
1.67 + while (it != _flexpages.end())
1.68 + {
1.69 + entry = it;
1.70 + it++;
1.71 +
1.72 + Flexpage *flexpage = entry->second;
1.73 +
1.74 + /* Some flexpages may be unavailable in the queue. Only those
1.75 + that can be reserved should be flushed and made available
1.76 + again. */
1.77 +
1.78 + if (pages->reserve(owner, flexpage))
1.79 + {
1.80 + owner->flush(flexpage, true);
1.81 + pages->release(flexpage);
1.82 + _flexpages.erase(entry);
1.83 + }
1.84 + }
1.85 +}
1.86 +
1.87 +/* Flush flexpages in the given range from 'start' with 'size', using 'owner'
1.88 + and 'pages'. */
1.89 +
1.90 +void AccessMap::flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages)
1.91 +{
1.92 + offset_t end = start + size;
1.93 +
1.94 + std::lock_guard<std::mutex> guard(_lock);
1.95 +
1.96 + /* The start may be within an existing flexpage where the flexpage size is a
1.97 + page multiple. */
1.98 +
1.99 + _AccessMap::iterator it = _flexpages.upper_bound(start), entry;
1.100 +
1.101 + if ((_flexpages.size() > 0) && (it != _flexpages.begin()))
1.102 + it--;
1.103 +
1.104 + /* Inspect flexpages at or after start until end. */
1.105 +
1.106 + while (it != _flexpages.end())
1.107 + {
1.108 + entry = it;
1.109 + it++;
1.110 +
1.111 + Flexpage *flexpage = entry->second;
1.112 +
1.113 + if (flexpage->base_offset >= end)
1.114 + break;
1.115 +
1.116 + /* Attempt to flush each flexpage, releasing ones that are no longer
1.117 + needed. */
1.118 +
1.119 + if (pages->reserve(owner, flexpage))
1.120 + {
1.121 + owner->flush(flexpage, false);
1.122 +
1.123 + /* Where no users of the flexpage persist, release the flexpage for
1.124 + reuse and remove this entry. */
1.125 +
1.126 + if (!flexpage->valid())
1.127 + {
1.128 + pages->release(flexpage);
1.129 + _flexpages.erase(entry);
1.130 + }
1.131 + else
1.132 + pages->queue(owner, flexpage);
1.133 + }
1.134 + }
1.135 +}
1.136 +
1.137 +// vim: tabstop=4 expandtab shiftwidth=4