X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fcommon%2FReadahead.h;fp=src%2Fceph%2Fsrc%2Fcommon%2FReadahead.h;h=26b05b67a3823a2c679412c6143d1b5b5f069007;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/common/Readahead.h b/src/ceph/src/common/Readahead.h new file mode 100644 index 0000000..26b05b6 --- /dev/null +++ b/src/ceph/src/common/Readahead.h @@ -0,0 +1,165 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_READAHEAD_H +#define CEPH_READAHEAD_H + +#include "Mutex.h" +#include "Cond.h" +#include + +/** + This class provides common state and logic for code that needs to perform readahead + on linear things such as RBD images or files. + Unless otherwise specified, all methods are thread-safe. + + Minimum and maximum readahead sizes may be violated by up to 50\% if alignment is enabled. + Minimum readahead size may be violated if the end of the readahead target is reached. + */ +class Readahead { +public: + typedef std::pair extent_t; + + // equal to UINT64_MAX + static const uint64_t NO_LIMIT = 18446744073709551615ULL; + + Readahead(); + + ~Readahead(); + + /** + Update state with new reads and return readahead to be performed. + If the length of the returned extent is 0, no readahead should be performed. + The readahead extent is guaranteed not to pass \c limit. + + Note that passing in NO_LIMIT as the limit and truncating the returned extent + is not the same as passing in the correct limit, because the internal state + will differ in the two cases. + + @param extents read operations since last call to update + @param limit size of the thing readahead is being applied to + */ + extent_t update(const vector& extents, uint64_t limit); + + /** + Update state with a new read and return readahead to be performed. + If the length of the returned extent is 0, no readahead should be performed. + The readahead extent is guaranteed not to pass \c limit. + + Note that passing in NO_LIMIT as the limit and truncating the returned extent + is not the same as passing in the correct limit, because the internal state + will differ in the two cases. + + @param offset offset of the read operation + @param length length of the read operation + @param limit size of the thing readahead is being applied to + */ + extent_t update(uint64_t offset, uint64_t length, uint64_t limit); + + /** + Increment the pending counter. + */ + void inc_pending(int count = 1); + + /** + Decrement the pending counter. + The counter must not be decremented below 0. + */ + void dec_pending(int count = 1); + + /** + Waits until the pending count reaches 0. + */ + void wait_for_pending(); + void wait_for_pending(Context *ctx); + + /** + Sets the number of sequential requests necessary to trigger readahead. + */ + void set_trigger_requests(int trigger_requests); + + /** + Gets the minimum size of a readahead request, in bytes. + */ + uint64_t get_min_readahead_size(void); + + /** + Gets the maximum size of a readahead request, in bytes. + */ + uint64_t get_max_readahead_size(void); + + /** + Sets the minimum size of a readahead request, in bytes. + */ + void set_min_readahead_size(uint64_t min_readahead_size); + + /** + Sets the maximum size of a readahead request, in bytes. + */ + void set_max_readahead_size(uint64_t max_readahead_size); + + /** + Sets the alignment units. + If the end point of a readahead request can be aligned to an alignment unit + by increasing or decreasing the size of the request by 50\% or less, it will. + Alignments are tested in order, so larger numbers should almost always come first. + */ + void set_alignments(const std::vector &alignments); + +private: + /** + Records that a read request has been received. + m_lock must be held while calling. + */ + void _observe_read(uint64_t offset, uint64_t length); + + /** + Computes the next readahead request. + m_lock must be held while calling. + */ + extent_t _compute_readahead(uint64_t limit); + + /// Number of sequential requests necessary to trigger readahead + int m_trigger_requests; + + /// Minimum size of a readahead request, in bytes + uint64_t m_readahead_min_bytes; + + /// Maximum size of a readahead request, in bytes + uint64_t m_readahead_max_bytes; + + /// Alignment units, in bytes + std::vector m_alignments; + + /// Held while reading/modifying any state except m_pending + Mutex m_lock; + + /// Number of consecutive read requests in the current sequential stream + int m_nr_consec_read; + + /// Number of bytes read in the current sequenial stream + uint64_t m_consec_read_bytes; + + /// Position of the read stream + uint64_t m_last_pos; + + /// Position of the readahead stream + uint64_t m_readahead_pos; + + /// When readahead is already triggered and the read stream crosses this point, readahead is continued + uint64_t m_readahead_trigger_pos; + + /// Size of the next readahead request (barring changes due to alignment, etc.) + uint64_t m_readahead_size; + + /// Number of pending readahead requests, as determined by inc_pending() and dec_pending() + int m_pending; + + /// Lock for m_pending + Mutex m_pending_lock; + + /// Waiters for pending readahead + std::list m_pending_waiting; +}; + +#endif