mirror of https://github.com/procxx/kepka.git
Improve working with cache in streaming.
This commit is contained in:
parent
b6a757842a
commit
44df10d6cb
|
@ -137,6 +137,7 @@ void Player::trackReceivedTill(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static auto wakes = 0;
|
||||||
template <typename Track>
|
template <typename Track>
|
||||||
void Player::trackPlayedTill(
|
void Player::trackPlayedTill(
|
||||||
const Track &track,
|
const Track &track,
|
||||||
|
@ -152,6 +153,7 @@ void Player::trackPlayedTill(
|
||||||
if (_pauseReading && !bothReceivedEnough(kLoadInAdvanceFor)) {
|
if (_pauseReading && !bothReceivedEnough(kLoadInAdvanceFor)) {
|
||||||
_pauseReading = false;
|
_pauseReading = false;
|
||||||
_file->wake();
|
_file->wake();
|
||||||
|
++wakes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +419,8 @@ bool Player::trackReceivedEnough(
|
||||||
const TrackState &state,
|
const TrackState &state,
|
||||||
crl::time amount) const {
|
crl::time amount) const {
|
||||||
return FullTrackReceived(state)
|
return FullTrackReceived(state)
|
||||||
|| (state.position + amount <= state.receivedTill);
|
|| (state.position != kTimeUnknown
|
||||||
|
&& state.position + amount <= state.receivedTill);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::bothReceivedEnough(crl::time amount) const {
|
bool Player::bothReceivedEnough(crl::time amount) const {
|
||||||
|
@ -569,6 +572,7 @@ Player::~Player() {
|
||||||
//
|
//
|
||||||
// So instead of maintaining it in the class definition as well we
|
// So instead of maintaining it in the class definition as well we
|
||||||
// simply call stop() here, after that the destruction is trivial.
|
// simply call stop() here, after that the destruction is trivial.
|
||||||
|
LOG(("WAKES: %1").arg(wakes));
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -357,19 +357,15 @@ auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult {
|
||||||
&& (fromSlice + 1 == tillSlice || fromSlice + 2 == tillSlice)
|
&& (fromSlice + 1 == tillSlice || fromSlice + 2 == tillSlice)
|
||||||
&& tillSlice <= _data.size());
|
&& tillSlice <= _data.size());
|
||||||
|
|
||||||
|
const auto cacheNotLoaded = [&](int sliceIndex) {
|
||||||
|
return (_headerMode != HeaderMode::NoCache)
|
||||||
|
&& (_headerMode != HeaderMode::Unknown)
|
||||||
|
&& !(_data[sliceIndex].flags & Flag::LoadedFromCache);
|
||||||
|
};
|
||||||
const auto handlePrepareResult = [&](
|
const auto handlePrepareResult = [&](
|
||||||
int sliceIndex,
|
int sliceIndex,
|
||||||
const Slice::PrepareFillResult &prepared) {
|
const Slice::PrepareFillResult &prepared) {
|
||||||
if (sliceIndex == _data.size()) {
|
if (cacheNotLoaded(sliceIndex)) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(_data[sliceIndex].flags & Flag::LoadedFromCache)
|
|
||||||
&& _headerMode != HeaderMode::NoCache
|
|
||||||
&& _headerMode != HeaderMode::Unknown) {
|
|
||||||
if (!(_data[sliceIndex].flags & Flag::LoadingFromCache)) {
|
|
||||||
_data[sliceIndex].flags |= Flag::LoadingFromCache;
|
|
||||||
result.sliceNumbersFromCache.add(sliceIndex + 1);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto offset : prepared.offsetsFromLoader.values()) {
|
for (const auto offset : prepared.offsetsFromLoader.values()) {
|
||||||
|
@ -379,7 +375,16 @@ auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const auto handleReadFromCache = [&](int sliceIndex) {
|
||||||
|
if (cacheNotLoaded(sliceIndex)
|
||||||
|
&& !(_data[sliceIndex].flags & Flag::LoadingFromCache)) {
|
||||||
|
_data[sliceIndex].flags |= Flag::LoadingFromCache;
|
||||||
|
if (sliceIndex == 23) {
|
||||||
|
int a = 0;
|
||||||
|
}
|
||||||
|
result.sliceNumbersFromCache.add(sliceIndex + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
const auto firstFrom = offset - fromSlice * kInSlice;
|
const auto firstFrom = offset - fromSlice * kInSlice;
|
||||||
const auto firstTill = std::min(kInSlice, till - fromSlice * kInSlice);
|
const auto firstTill = std::min(kInSlice, till - fromSlice * kInSlice);
|
||||||
const auto secondFrom = 0;
|
const auto secondFrom = 0;
|
||||||
|
@ -389,7 +394,9 @@ auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult {
|
||||||
? _data[fromSlice + 1].prepareFill(secondFrom, secondTill)
|
? _data[fromSlice + 1].prepareFill(secondFrom, secondTill)
|
||||||
: Slice::PrepareFillResult();
|
: Slice::PrepareFillResult();
|
||||||
handlePrepareResult(fromSlice, first);
|
handlePrepareResult(fromSlice, first);
|
||||||
handlePrepareResult(fromSlice + 1, second);
|
if (fromSlice + 1 < tillSlice) {
|
||||||
|
handlePrepareResult(fromSlice + 1, second);
|
||||||
|
}
|
||||||
if (first.ready && second.ready) {
|
if (first.ready && second.ready) {
|
||||||
markSliceUsed(fromSlice);
|
markSliceUsed(fromSlice);
|
||||||
CopyLoaded(
|
CopyLoaded(
|
||||||
|
@ -405,18 +412,13 @@ auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult {
|
||||||
secondFrom,
|
secondFrom,
|
||||||
secondTill);
|
secondTill);
|
||||||
}
|
}
|
||||||
if (_usedSlices.size() > kSlicesInMemory
|
result.toCache = serializeAndUnloadUnused();
|
||||||
&& _headerMode != HeaderMode::Unknown) {
|
|
||||||
const auto purgeSlice = _usedSlices.front();
|
|
||||||
_usedSlices.pop_front();
|
|
||||||
if (_headerMode == HeaderMode::NoCache
|
|
||||||
|| !(_data[purgeSlice].flags & Flag::ChangedSinceCache)) {
|
|
||||||
_data[purgeSlice] = Slice();
|
|
||||||
} else {
|
|
||||||
result.toCache = serializeAndUnloadSlice(purgeSlice + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.filled = true;
|
result.filled = true;
|
||||||
|
} else {
|
||||||
|
handleReadFromCache(fromSlice);
|
||||||
|
if (fromSlice + 1 < tillSlice) {
|
||||||
|
handleReadFromCache(fromSlice + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -442,6 +444,24 @@ int Reader::Slices::maxSliceSize(int sliceNumber) const {
|
||||||
: _size;
|
: _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reader::SerializedSlice Reader::Slices::serializeAndUnloadUnused() {
|
||||||
|
if (_headerMode == HeaderMode::Unknown
|
||||||
|
|| _usedSlices.size() <= kSlicesInMemory) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto purgeSlice = _usedSlices.front();
|
||||||
|
_usedSlices.pop_front();
|
||||||
|
if (!(_data[purgeSlice].flags & Slice::Flag::LoadedFromCache)) {
|
||||||
|
// If the only data in this slice was from _header, just leave it.
|
||||||
|
return {};
|
||||||
|
} else if (_headerMode == HeaderMode::NoCache
|
||||||
|
|| !(_data[purgeSlice].flags & Slice::Flag::ChangedSinceCache)) {
|
||||||
|
_data[purgeSlice] = Slice();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return serializeAndUnloadSlice(purgeSlice + 1);
|
||||||
|
}
|
||||||
|
|
||||||
Reader::SerializedSlice Reader::Slices::serializeAndUnloadSlice(
|
Reader::SerializedSlice Reader::Slices::serializeAndUnloadSlice(
|
||||||
int sliceNumber) {
|
int sliceNumber) {
|
||||||
Expects(sliceNumber >= 0 && sliceNumber <= _data.size());
|
Expects(sliceNumber >= 0 && sliceNumber <= _data.size());
|
||||||
|
|
|
@ -127,6 +127,7 @@ private:
|
||||||
void applyHeaderCacheData();
|
void applyHeaderCacheData();
|
||||||
int maxSliceSize(int sliceNumber) const;
|
int maxSliceSize(int sliceNumber) const;
|
||||||
SerializedSlice serializeAndUnloadSlice(int sliceNumber);
|
SerializedSlice serializeAndUnloadSlice(int sliceNumber);
|
||||||
|
SerializedSlice serializeAndUnloadUnused();
|
||||||
void markSliceUsed(int sliceIndex);
|
void markSliceUsed(int sliceIndex);
|
||||||
|
|
||||||
std::vector<Slice> _data;
|
std::vector<Slice> _data;
|
||||||
|
|
Loading…
Reference in New Issue