blob: 2022efc1f455284ca0aab4e04f68ee153ec19b11 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#pragma once
#include "runtime/exec_env.h"
#include "storage/cache/page_cache.h"
#include "util/slice.h" // for Slice
namespace doris {
// After disable page cache, sometimes we need to know the percentage of data pages in query memory.
inline bvar::Adder<int64_t> g_page_no_cache_mem_bytes("doris_page_no_cache_mem_bytes");
namespace segment_v2 {
// When a column page is read into memory, we use this to store it.
// A page's data may be in cache, or may not in cache. We use this
// class to unify these two cases.
// If client use this struct to wrap data not in cache, this class
// will free data's memory when it is destroyed.
class PageHandle {
public:
PageHandle() : _is_data_owner(false) {}
// This class will take the ownership of input data's memory. It will
// free it when deconstructs.
PageHandle(DataPage* data) : _is_data_owner(true), _data(data) {
g_page_no_cache_mem_bytes << _data->capacity();
}
// This class will take the content of cache data, and will make input
// cache_data to a invalid cache handle.
PageHandle(PageCacheHandle cache_data)
: _is_data_owner(false), _cache_data(std::move(cache_data)) {}
// Move constructor
PageHandle(PageHandle&& other) noexcept : _cache_data(std::move(other._cache_data)) {
// we can use std::exchange if we switch c++14 on
std::swap(_is_data_owner, other._is_data_owner);
std::swap(_data, other._data);
}
PageHandle& operator=(PageHandle&& other) noexcept {
std::swap(_is_data_owner, other._is_data_owner);
std::swap(_data, other._data);
_cache_data = std::move(other._cache_data);
return *this;
}
~PageHandle() {
if (_is_data_owner) {
g_page_no_cache_mem_bytes << -_data->capacity();
delete _data;
} else {
DCHECK(_data == nullptr);
}
}
// the return slice contains uncompressed page body, page footer, and footer size
Slice data() const {
if (_is_data_owner) {
return Slice(_data->data(), _data->size());
} else {
return _cache_data.data();
}
}
private:
// when this is true, it means this struct own data and _data is valid.
// otherwise _cache_data is valid, and data is belong to cache.
bool _is_data_owner = false;
DataPage* _data = nullptr;
PageCacheHandle _cache_data;
// Don't allow copy and assign
DISALLOW_COPY_AND_ASSIGN(PageHandle);
};
} // namespace segment_v2
} // namespace doris