pmt: New features and improvements

- Added type getter and reboot function
 - Writed a garbage collector, so manually freeing memory and closing file descriptors is removed
 - Some other improvements
This commit is contained in:
2025-08-09 12:48:04 +03:00
parent 8b3e886eee
commit 8e629d60d0
28 changed files with 1826 additions and 1265 deletions

View File

@@ -20,78 +20,71 @@
#include <libpartition_map/lib.hpp>
namespace PartitionMap {
Map_t basic_partition_map_builder::getAll() const {
_map_build_check();
return _current_map;
}
Map_t basic_partition_map_builder::getAll() const
{
_map_build_check();
return _current_map;
}
std::optional<std::pair<uint64_t, bool> > basic_partition_map_builder::get(const std::string_view name) const {
_map_build_check();
std::optional<std::pair<uint64_t, bool>> basic_partition_map_builder::get(const std::string_view name) const
{
_map_build_check();
if (!_current_map.find(name)) return std::nullopt;
return std::make_pair(_current_map.get_size(name), _current_map.is_logical(name));
}
if (!_current_map.find(name)) return std::nullopt;
return std::make_pair(_current_map.get_size(name), _current_map.is_logical(name));
}
std::optional<std::list<std::string> > basic_partition_map_builder::getLogicalPartitionList() const {
_map_build_check();
std::optional<std::list<std::string>> basic_partition_map_builder::getLogicalPartitionList() const
{
_map_build_check();
std::list<std::string> logicals;
for (const auto &[name, props]: _current_map)
if (props.isLogical) logicals.push_back(name);
std::list<std::string> logicals;
for (const auto& [name, props] : _current_map)
if (props.isLogical) logicals.push_back(name);
if (logicals.empty()) return std::nullopt;
return logicals;
}
if (logicals.empty()) return std::nullopt;
return logicals;
}
std::optional<std::list<std::string> > basic_partition_map_builder::getPhysicalPartitionList() const {
_map_build_check();
std::optional<std::list<std::string>> basic_partition_map_builder::getPhysicalPartitionList() const
{
_map_build_check();
std::list<std::string> physicals;
for (const auto &[name, props]: _current_map)
if (!props.isLogical) physicals.push_back(name);
std::list<std::string> physicals;
for (const auto& [name, props] : _current_map)
if (!props.isLogical) physicals.push_back(name);
if (physicals.empty()) return std::nullopt;
return physicals;
}
if (physicals.empty()) return std::nullopt;
return physicals;
}
std::optional<std::list<std::string> > basic_partition_map_builder::getPartitionList() const {
_map_build_check();
std::optional<std::list<std::string>> basic_partition_map_builder::getPartitionList() const {
_map_build_check();
std::list<std::string> partitions;
for (const auto &[name, props]: _current_map) partitions.push_back(name);
std::list<std::string> partitions;
for (const auto& [name, props] : _current_map) partitions.push_back(name);
if (partitions.empty()) return std::nullopt;
return partitions;
}
if (partitions.empty()) return std::nullopt;
return partitions;
}
std::string basic_partition_map_builder::getRealLinkPathOf(const std::string_view name) const {
_map_build_check();
std::string basic_partition_map_builder::getRealLinkPathOf(const std::string_view name) const
{
_map_build_check();
if (!_current_map.find(name)) return {};
return std::string(_workdir + "/" + name.data());
}
if (!_current_map.find(name)) return {};
return std::string(_workdir + "/" + name.data());
}
std::string basic_partition_map_builder::getRealPathOf(const std::string_view name) const {
_map_build_check();
std::string basic_partition_map_builder::getRealPathOf(const std::string_view name) const
{
_map_build_check();
const std::string full = (isLogical(name))
? std::string("/dev/block/mapper/") + name.data()
: _workdir + "/" + name.data();
if (!_current_map.find(name)
|| !std::filesystem::is_symlink(full))
return {};
const std::string full = (isLogical(name)) ? std::string("/dev/block/mapper/") + name.data() : _workdir + "/" + name.data();
if (!_current_map.find(name)
|| !std::filesystem::is_symlink(full))
return {};
return std::filesystem::read_symlink(full);
}
std::string basic_partition_map_builder::getCurrentWorkDir() const
{
return _workdir;
}
return std::filesystem::read_symlink(full);
}
std::string basic_partition_map_builder::getCurrentWorkDir() const {
return _workdir;
}
} // namespace PartitionMap

View File

@@ -0,0 +1,119 @@
/*
Copyright 2025 Yağız Zengin
Licensed 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.
*/
#include <fcntl.h>
#include <unistd.h>
#include <sstream>
#include <string>
#include <unordered_map>
#include <libhelper/lib.hpp>
#include <libpartition_map/lib.hpp>
#include "PartitionManager/PartitionManager.hpp"
namespace PartitionMap::Extras {
std::unordered_map<uint64_t, std::string> FileSystemMagicMap = {
{FileSystemMagic::EXTFS_FS, "EXT2/3/4"},
{FileSystemMagic::F2FS_FS, "F2FS"},
{FileSystemMagic::EROFS_FS, "EROFS"},
{FileSystemMagic::EXFAT_FS, "exFAT"},
{FileSystemMagic::FAT12_FS, "FAT12"},
{FileSystemMagic::FAT16_FS, "FAT16"},
{FileSystemMagic::FAT32_FS, "FAT32"},
{FileSystemMagic::NTFS_FS, "NTFS"},
{FileSystemMagic::MSDOS_FS, "MSDOS"}
};
std::unordered_map<uint64_t, std::string> AndroidMagicMap = {
{AndroidMagic::BOOT_IMAGE, "Android Boot Image"},
{AndroidMagic::VBOOT_IMAGE, "Android Vendor Boot Image"},
{AndroidMagic::LK_IMAGE, "Android LK (Bootloader)"},
{AndroidMagic::DTBO_IMAGE, "Android DTBO Image"},
{AndroidMagic::VBMETA_IMAGE, "Android VBMeta Image"},
{AndroidMagic::SUPER_IMAGE, "Android Super Image"},
{AndroidMagic::SPARSE_IMAGE, "Android Sparse Image"},
{AndroidMagic::ELF, "ELF"},
{AndroidMagic::RAW, "Raw Data"}
};
std::unordered_map<uint64_t, std::string> MagicMap = {
{AndroidMagic::BOOT_IMAGE, "Android Boot Image"},
{AndroidMagic::VBOOT_IMAGE, "Android Vendor Boot Image"},
{AndroidMagic::LK_IMAGE, "Android LK (Bootloader)"},
{AndroidMagic::DTBO_IMAGE, "Android DTBO Image"},
{AndroidMagic::VBMETA_IMAGE, "Android VBMeta Image"},
{AndroidMagic::SUPER_IMAGE, "Android Super Image"},
{AndroidMagic::SPARSE_IMAGE, "Android Sparse Image"},
{AndroidMagic::ELF, "ELF"},
{AndroidMagic::RAW, "Raw Data"},
{FileSystemMagic::EXTFS_FS, "EXT2/3/4"},
{FileSystemMagic::F2FS_FS, "F2FS"},
{FileSystemMagic::EROFS_FS, "EROFS"},
{FileSystemMagic::EXFAT_FS, "exFAT"},
{FileSystemMagic::FAT12_FS, "FAT12"},
{FileSystemMagic::FAT16_FS, "FAT16"},
{FileSystemMagic::FAT32_FS, "FAT32"},
{FileSystemMagic::NTFS_FS, "NTFS"},
{FileSystemMagic::MSDOS_FS, "MSDOS"}
};
size_t getMagicLength(const uint64_t magic) {
size_t length = 0;
for (int i = 0; i < 8; i++) {
if ((magic >> (8 * i)) & 0xFF) length = i + 1;
}
return length;
}
bool hasMagic(const uint64_t magic, const ssize_t buf, const std::string &path) {
LOGN(MAP, INFO) << "Checking magic of " << path << " with using " << buf << " byte buffer size (has magic 0x" << std::hex << magic << "?)" << std::endl;
Helper::garbageCollector collector;
const int fd = Helper::openAndAddToCloseList(path, collector, O_RDONLY);
if (fd < 0) return false;
if (buf < 1) {
LOGN(MAP, ERROR) << "Buffer size is older than 1" << std::endl;
return false;
}
auto *buffer = new uint8_t[buf];
collector.delAfterProgress(buffer);
const ssize_t bytesRead = read(fd, buffer, buf);
if (bytesRead < 0) return false;
const size_t magicLength = getMagicLength(magic);
if (magicLength == 0) return false;
for (size_t i = 0; i <= bytesRead - magicLength; i++) {
uint64_t value = 0;
for (size_t j = 0; j < magicLength; ++j) value |= static_cast<uint64_t>(buffer[i + j]) << (8 * j);
if (value == magic) {
LOGN(MAP, INFO) << path << " contains 0x" << std::hex << magic << std::endl;
return true;
}
}
LOGN(MAP, INFO) << path << " is not contains 0x" << std::hex << magic << std::endl;
return false;
}
std::string formatMagic(const uint64_t magic) {
std::stringstream ss;
ss << "0x" << std::uppercase << std::hex << std::setw(16) << std::setfill('0') << magic;
return ss.str();
}
} // namespace PartitionMap::Extras

View File

@@ -39,216 +39,197 @@ static constexpr std::array<std::string_view, 3> defaultEntryList = {
};
namespace PartitionMap {
bool basic_partition_map_builder::_is_real_block_dir(const std::string_view path)
{
if (path.find("/block/") == std::string::npos) {
LOGN(MAP, ERROR) << "Path " << path << " is not a real block directory.";
return false;
}
return true;
}
Map_t basic_partition_map_builder::_build_map(std::string_view path, bool logical)
{
Map_t map;
std::vector<std::filesystem::directory_entry> entries{std::filesystem::directory_iterator(path), std::filesystem::directory_iterator()};
std::sort(entries.begin(), entries.end(), [](const auto& a, const auto& b) {
return a.path().filename() < b.path().filename();
});
LOGN_IF(MAP, WARNING, entries.empty()) << "" << path << "is exists but generated vector is empty (std::vector<std::filesystem::directory_entry>)." << std::endl;
for (const auto& entry : entries) {
if (entry.path().filename() != "by-uuid"
&& std::string(entry.path()).find("com.") == std::string::npos)
map.insert(entry.path().filename().string(), _get_size(entry.path()), logical);
bool basic_partition_map_builder::_is_real_block_dir(const std::string_view path) {
if (path.find("/block/") == std::string::npos) {
LOGN(MAP, ERROR) << "Path " << path << " is not a real block directory.";
return false;
}
return true;
}
LOGN(MAP, INFO) << std::boolalpha << "Map generated successfully. is_logical_map=" << logical << std::endl;
return map;
}
Map_t basic_partition_map_builder::_build_map(std::string_view path, bool logical) {
Map_t map;
std::vector<std::filesystem::directory_entry> entries{
std::filesystem::directory_iterator(path), std::filesystem::directory_iterator()
};
std::sort(entries.begin(), entries.end(), [](const auto &a, const auto &b) {
return a.path().filename() < b.path().filename();
});
void basic_partition_map_builder::_insert_logicals(Map_t&& logicals)
{
LOGN(MAP, INFO) << "merging created logical partition list to this object's variable." << std::endl;
_current_map.merge(logicals);
}
LOGN_IF(MAP, WARNING, entries.empty()) << "" << path <<
"is exists but generated vector is empty (std::vector<std::filesystem::directory_entry>)." << std::endl;
for (const auto &entry: entries) {
if (entry.path().filename() != "by-uuid"
&& std::string(entry.path()).find("com.") == std::string::npos)
map.insert(entry.path().filename().string(), _get_size(entry.path()), logical);
}
void basic_partition_map_builder::_map_build_check() const
{
if (!_map_builded)
throw Error("Please build partition map before!");
}
uint64_t basic_partition_map_builder::_get_size(const std::string& path)
{
const std::string real = std::filesystem::read_symlink(path);
const int fd = open(real.data(), O_RDONLY);
if (fd < 0) {
LOGN(MAP, ERROR) << "Cannot open " << real << ": " << strerror(errno) << std::endl;
return 0;
LOGN(MAP, INFO) << std::boolalpha << "Map generated successfully. is_logical_map=" << logical << std::endl;
return map;
}
uint64_t size = 0;
if (ioctl(fd, BLKGETSIZE64, &size) != 0) {
close(fd);
LOGN(MAP, ERROR) << "ioctl() process failed for " << real << ": " << strerror(errno) << std::endl;
return 0;
void basic_partition_map_builder::_insert_logicals(Map_t &&logicals) {
LOGN(MAP, INFO) << "merging created logical partition list to this object's variable." << std::endl;
_current_map.merge(logicals);
}
close(fd);
return size;
}
void basic_partition_map_builder::_map_build_check() const {
if (!_map_builded)
throw Error("Please build partition map before!");
}
basic_partition_map_builder::basic_partition_map_builder()
{
LOGN(MAP, INFO) << "default constructor called. Starting build." << std::endl;
uint64_t basic_partition_map_builder::_get_size(const std::string &path) {
const std::string real = std::filesystem::read_symlink(path);
Helper::garbageCollector collector;
for (const auto& path : defaultEntryList) {
if (std::filesystem::exists(path)) {
_current_map = _build_map(path);
if (_current_map.empty()) {
_any_generating_error = true;
} else {
_workdir = path;
break;
const int fd = Helper::openAndAddToCloseList(real, collector, O_RDONLY);
if (fd < 0) {
LOGN(MAP, ERROR) << "Cannot open " << real << ": " << strerror(errno) << std::endl;
return 0;
}
uint64_t size = 0;
if (ioctl(fd, BLKGETSIZE64, &size) != 0) {
LOGN(MAP, ERROR) << "ioctl() process failed for " << real << ": " << strerror(errno) << std::endl;
return 0;
}
return size;
}
basic_partition_map_builder::basic_partition_map_builder() {
LOGN(MAP, INFO) << "default constructor called. Starting build." << std::endl;
for (const auto &path: defaultEntryList) {
if (std::filesystem::exists(path)) {
_current_map = _build_map(path);
if (_current_map.empty()) {
_any_generating_error = true;
} else {
_workdir = path;
break;
}
}
}
if (_current_map.empty())
LOGN(MAP, ERROR) << "Cannot build map by any default search entry." << std::endl;
LOGN(MAP, INFO) << "default constructor successfully ended work." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
}
if (_current_map.empty())
LOGN(MAP, ERROR) << "Cannot build map by any default search entry." << std::endl;
basic_partition_map_builder::basic_partition_map_builder(const std::string_view path) {
LOGN(MAP, INFO) << "argument-based constructor called. Starting build." << std::endl;
LOGN(MAP, INFO) << "default constructor successfully ended work." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
}
basic_partition_map_builder::basic_partition_map_builder(const std::string_view path)
{
LOGN(MAP, INFO) << "argument-based constructor called. Starting build." << std::endl;
if (std::filesystem::exists(path)) {
if (!_is_real_block_dir(path)) return;
_current_map = _build_map(path);
if (_current_map.empty()) _any_generating_error = true;
else _workdir = path;
} else
throw Error("Cannot find directory: %s. Cannot build partition map!", path.data());
LOGN(MAP, INFO) << "argument-based constructor successfully ended work." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
}
bool basic_partition_map_builder::hasPartition(const std::string_view name) const
{
_map_build_check();
return _current_map.find(name);
}
bool basic_partition_map_builder::isLogical(const std::string_view name) const
{
_map_build_check();
return _current_map.is_logical(name);
}
void basic_partition_map_builder::clear()
{
_current_map.clear();
_workdir.clear();
_any_generating_error = false;
}
bool basic_partition_map_builder::readDirectory(const std::string_view path)
{
_map_builded = false;
LOGN(MAP, INFO) << "read " << path << " directory request." << std::endl;
if (std::filesystem::exists(path)) {
if (!_is_real_block_dir(path)) return false;
_current_map = _build_map(path);
if (_current_map.empty()) {
_any_generating_error = true;
return false;
} else _workdir = path;
} else
throw Error("Cannot find directory: %s. Cannot build partition map!", path.data());
LOGN(MAP, INFO) << "read " << path << " successfull." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
return true;
}
bool basic_partition_map_builder::readDefaultDirectories()
{
_map_builded = false;
LOGN(MAP, INFO) << "read default directories request." << std::endl;
for (const auto& path : defaultEntryList) {
if (std::filesystem::exists(path)) {
if (!_is_real_block_dir(path)) return;
_current_map = _build_map(path);
if (_current_map.empty()) _any_generating_error = true;
else _workdir = path;
} else
throw Error("Cannot find directory: %s. Cannot build partition map!", path.data());
LOGN(MAP, INFO) << "argument-based constructor successfully ended work." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
}
bool basic_partition_map_builder::hasPartition(const std::string_view name) const {
_map_build_check();
return _current_map.find(name);
}
bool basic_partition_map_builder::isLogical(const std::string_view name) const {
_map_build_check();
return _current_map.is_logical(name);
}
void basic_partition_map_builder::clear() {
_current_map.clear();
_workdir.clear();
_any_generating_error = false;
}
bool basic_partition_map_builder::readDirectory(const std::string_view path) {
_map_builded = false;
LOGN(MAP, INFO) << "read " << path << " directory request." << std::endl;
if (std::filesystem::exists(path)) {
if (!_is_real_block_dir(path)) return false;
_current_map = _build_map(path);
if (_current_map.empty()) {
_any_generating_error = true;
return false;
} else {
_workdir = path;
break;
}
}
} else _workdir = path;
} else
throw Error("Cannot find directory: %s. Cannot build partition map!", path.data());
LOGN(MAP, INFO) << "read " << path << " successfull." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
return true;
}
if (_current_map.empty())
LOGN(MAP, ERROR) << "Cannot build map by any default search entry." << std::endl;
bool basic_partition_map_builder::readDefaultDirectories() {
_map_builded = false;
LOGN(MAP, INFO) << "read default directories request." << std::endl;
LOGN(MAP, INFO) << "read default directories successfull." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
return true;
}
for (const auto &path: defaultEntryList) {
if (std::filesystem::exists(path)) {
_current_map = _build_map(path);
if (_current_map.empty()) {
_any_generating_error = true;
return false;
} else {
_workdir = path;
break;
}
}
}
bool basic_partition_map_builder::empty() const
{
_map_build_check();
return _current_map.empty();
}
if (_current_map.empty())
LOGN(MAP, ERROR) << "Cannot build map by any default search entry." << std::endl;
uint64_t basic_partition_map_builder::sizeOf(const std::string_view name) const
{
_map_build_check();
return _current_map.get_size(name);
}
LOGN(MAP, INFO) << "read default directories successfull." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
return true;
}
bool operator==(const basic_partition_map_builder& lhs, const basic_partition_map_builder& rhs)
{
return lhs._current_map == rhs._current_map;
}
bool basic_partition_map_builder::empty() const {
_map_build_check();
return _current_map.empty();
}
bool operator!=(const basic_partition_map_builder& lhs, const basic_partition_map_builder& rhs)
{
return !(lhs == rhs);
}
uint64_t basic_partition_map_builder::sizeOf(const std::string_view name) const {
_map_build_check();
return _current_map.get_size(name);
}
basic_partition_map_builder::operator bool() const
{
return !this->_any_generating_error;
}
bool operator==(const basic_partition_map_builder &lhs, const basic_partition_map_builder &rhs) {
return lhs._current_map == rhs._current_map;
}
bool basic_partition_map_builder::operator!() const
{
return this->_any_generating_error;
}
bool operator!=(const basic_partition_map_builder &lhs, const basic_partition_map_builder &rhs) {
return !(lhs == rhs);
}
bool basic_partition_map_builder::operator()(const std::string_view path)
{
LOGN(MAP, INFO) << "calling readDirectory() for building map with " << path << std::endl;
return readDirectory(path);
}
basic_partition_map_builder::operator bool() const {
return !this->_any_generating_error;
}
std::string getLibVersion()
{
MKVERSION("libpartition_map");
}
bool basic_partition_map_builder::operator!() const {
return this->_any_generating_error;
}
bool basic_partition_map_builder::operator()(const std::string_view path) {
LOGN(MAP, INFO) << "calling readDirectory() for building map with " << path << std::endl;
return readDirectory(path);
}
std::string getLibVersion() {
MKVERSION("libpartition_map");
}
} // namespace PartitionMap

View File

@@ -20,250 +20,217 @@
#include <libpartition_map/lib.hpp>
namespace PartitionMap {
basic_partition_map::iterator::iterator(_entry* p) : ptr(p) {}
auto basic_partition_map::iterator::operator*() const -> std::pair<std::string&, decltype(_entry::props)&>
{
return {ptr->name, ptr->props};
}
_entry* basic_partition_map::iterator::operator->() const
{
return ptr;
}
basic_partition_map::iterator& basic_partition_map::iterator::operator++()
{
++ptr;
return *this;
}
basic_partition_map::iterator basic_partition_map::iterator::operator++(int)
{
iterator tmp = *this;
++ptr;
return tmp;
}
bool basic_partition_map::iterator::operator==(const iterator& other) const
{
return ptr == other.ptr;
}
bool basic_partition_map::iterator::operator!=(const iterator& other) const
{
return ptr != other.ptr;
}
basic_partition_map::constant_iterator::constant_iterator(const _entry* p) : ptr(p) {}
auto basic_partition_map::constant_iterator::operator*() const -> std::pair<const std::string&, const decltype(_entry::props)&> {
return {ptr->name, ptr->props};
}
const _entry* basic_partition_map::constant_iterator::operator->() const
{
return ptr;
}
basic_partition_map::constant_iterator& basic_partition_map::constant_iterator::operator++()
{
++ptr;
return *this;
}
basic_partition_map::constant_iterator basic_partition_map::constant_iterator::operator++(int)
{
constant_iterator tmp = *this;
++ptr;
return tmp;
}
bool basic_partition_map::constant_iterator::operator==(const constant_iterator& other) const
{
return ptr == other.ptr;
}
bool basic_partition_map::constant_iterator::operator!=(const constant_iterator& other) const
{
return ptr != other.ptr;
}
void basic_partition_map::_resize_map()
{
const size_t new_capacity = _capacity * 2;
auto* new_data = new _entry[new_capacity];
for (size_t i = 0; i < _count; i++) new_data[i] = _data[i];
delete[] _data;
_data = new_data;
_capacity = new_capacity;
}
int basic_partition_map::_index_of(const std::string_view name) const
{
for (size_t i = 0; i < _count; i++) {
if (name == _data[i].name) return static_cast<int>(i);
basic_partition_map::iterator::iterator(_entry *p) : ptr(p) {
}
return 0;
}
auto basic_partition_map::iterator::operator*() const -> std::pair<std::string &, decltype(_entry::props) &> {
return {ptr->name, ptr->props};
}
basic_partition_map::basic_partition_map(const std::string& name, const uint64_t size, const bool logical)
{
_data = new _entry[_capacity];
insert(name, size, logical);
}
_entry *basic_partition_map::iterator::operator->() const {
return ptr;
}
basic_partition_map::basic_partition_map(const basic_partition_map& other) :
_data(new _entry[other._capacity]),
_count(other._count),
_capacity(other._capacity)
{
std::copy(other._data, other._data + _count, _data);
}
basic_partition_map::iterator &basic_partition_map::iterator::operator++() {
++ptr;
return *this;
}
basic_partition_map::basic_partition_map() : _capacity(6)
{
_data = new _entry[_capacity];
}
basic_partition_map::iterator basic_partition_map::iterator::operator++(int) {
iterator tmp = *this;
++ptr;
return tmp;
}
basic_partition_map::~basic_partition_map()
{
delete[] _data;
}
bool basic_partition_map::iterator::operator==(const iterator &other) const {
return ptr == other.ptr;
}
bool basic_partition_map::insert(const std::string& name, const uint64_t size, const bool logical)
{
if (name == _data[_index_of(name)].name) return false;
if (_count == _capacity) _resize_map();
bool basic_partition_map::iterator::operator!=(const iterator &other) const {
return ptr != other.ptr;
}
_data[_count++] = {name, {size, logical}};
LOGN(MAP, INFO) << std::boolalpha << "partition " << name << " inserted (size=" << size << ", is_logical=" << logical << ")." << std::endl;
return true;
}
basic_partition_map::constant_iterator::constant_iterator(const _entry *p) : ptr(p) {
}
void basic_partition_map::merge(const basic_partition_map& map)
{
LOGN(MAP, INFO) << "map merge request." << std::endl;
for (const auto& [name, props] : map)
insert(name, props.size, props.isLogical);
LOGN(MAP, INFO) << "map merged successfully." << std::endl;
}
auto basic_partition_map::constant_iterator::operator
*() const -> std::pair<const std::string &, const decltype(_entry::props) &> {
return {ptr->name, ptr->props};
}
uint64_t basic_partition_map::get_size(const std::string_view name) const
{
if (const int pos = _index_of(name); name == _data[pos].name) return _data[pos].props.size;
return 0;
}
const _entry *basic_partition_map::constant_iterator::operator->() const {
return ptr;
}
bool basic_partition_map::is_logical(const std::string_view name) const
{
if (const int pos = _index_of(name); name == _data[pos].name) return _data[pos].props.isLogical;
basic_partition_map::constant_iterator &basic_partition_map::constant_iterator::operator++() {
++ptr;
return *this;
}
return false;
}
basic_partition_map::constant_iterator basic_partition_map::constant_iterator::operator++(int) {
constant_iterator tmp = *this;
++ptr;
return tmp;
}
basic_partition_map::_returnable_entry basic_partition_map::get_all(const std::string_view name) const
{
if (const int pos = _index_of(name); name == _data[pos].name)
return _returnable_entry{_data[pos].props.size, _data[pos].props.isLogical};
bool basic_partition_map::constant_iterator::operator==(const constant_iterator &other) const {
return ptr == other.ptr;
}
return _returnable_entry{};
}
bool basic_partition_map::constant_iterator::operator!=(const constant_iterator &other) const {
return ptr != other.ptr;
}
bool basic_partition_map::find(const std::string_view name) const
{
if (name == _data[_index_of(name)].name) return true;
void basic_partition_map::_resize_map() {
const size_t new_capacity = _capacity * 2;
auto *new_data = new _entry[new_capacity];
return false;
}
for (size_t i = 0; i < _count; i++) new_data[i] = _data[i];
std::string basic_partition_map::find_(const std::string& name) const
{
if (name == _data[_index_of(name)].name) return name;
return {};
}
size_t basic_partition_map::size() const
{
return _count;
}
bool basic_partition_map::empty() const
{
if (_count > 0) return false;
return true;
}
void basic_partition_map::clear()
{
LOGN(MAP, INFO) << "map clean requested. Map is empty now." << std::endl;
delete[] _data;
_count = 0;
_capacity = 6;
_data = new _entry[_capacity];
}
basic_partition_map& basic_partition_map::operator=(const basic_partition_map& map)
{
if (this != &map) {
delete[] _data;
_capacity = map._capacity;
_count = map._count;
_data = new _entry[_capacity];
std::copy(map._data, map._data + _count, _data);
_data = new_data;
_capacity = new_capacity;
}
return *this;
}
int basic_partition_map::_index_of(const std::string_view name) const {
for (size_t i = 0; i < _count; i++) {
if (name == _data[i].name) return static_cast<int>(i);
}
return 0;
}
basic_partition_map::basic_partition_map(const std::string &name, const uint64_t size, const bool logical) {
_data = new _entry[_capacity];
insert(name, size, logical);
}
basic_partition_map::basic_partition_map(const basic_partition_map &other) : _data(new _entry[other._capacity]),
_count(other._count),
_capacity(other._capacity) {
std::copy(other._data, other._data + _count, _data);
}
basic_partition_map::basic_partition_map() : _capacity(6) {
_data = new _entry[_capacity];
}
basic_partition_map::~basic_partition_map() {
delete[] _data;
}
bool basic_partition_map::insert(const std::string &name, const uint64_t size, const bool logical) {
if (name == _data[_index_of(name)].name) return false;
if (_count == _capacity) _resize_map();
_data[_count++] = {name, {size, logical}};
LOGN(MAP, INFO) << std::boolalpha << "partition " << name << " inserted (size=" << size << ", is_logical=" <<
logical << ")." << std::endl;
return true;
}
void basic_partition_map::merge(const basic_partition_map &map) {
LOGN(MAP, INFO) << "map merge request." << std::endl;
for (const auto &[name, props]: map)
insert(name, props.size, props.isLogical);
LOGN(MAP, INFO) << "map merged successfully." << std::endl;
}
uint64_t basic_partition_map::get_size(const std::string_view name) const {
if (const int pos = _index_of(name); name == _data[pos].name) return _data[pos].props.size;
return 0;
}
bool basic_partition_map::is_logical(const std::string_view name) const {
if (const int pos = _index_of(name); name == _data[pos].name) return _data[pos].props.isLogical;
bool basic_partition_map::operator==(const basic_partition_map& other) const
{
if (this->_capacity != other._capacity
|| this->_count != other._count)
return false;
}
for (size_t i = 0; i < _count; i++)
if (_data[i].name == other._data[i].name
&& _data[i].props.size == other._data[i].props.size
&& _data[i].props.isLogical == other._data[i].props.isLogical)
continue;
else
basic_partition_map::_returnable_entry basic_partition_map::get_all(const std::string_view name) const {
if (const int pos = _index_of(name); name == _data[pos].name)
return _returnable_entry{_data[pos].props.size, _data[pos].props.isLogical};
return _returnable_entry{};
}
bool basic_partition_map::find(const std::string_view name) const {
if (name == _data[_index_of(name)].name) return true;
return false;
}
std::string basic_partition_map::find_(const std::string &name) const {
if (name == _data[_index_of(name)].name) return name;
return {};
}
size_t basic_partition_map::size() const {
return _count;
}
bool basic_partition_map::empty() const {
if (_count > 0) return false;
return true;
}
void basic_partition_map::clear() {
LOGN(MAP, INFO) << "map clean requested. Map is empty now." << std::endl;
delete[] _data;
_count = 0;
_capacity = 6;
_data = new _entry[_capacity];
}
basic_partition_map &basic_partition_map::operator=(const basic_partition_map &map) {
if (this != &map) {
delete[] _data;
_capacity = map._capacity;
_count = map._count;
_data = new _entry[_capacity];
std::copy(map._data, map._data + _count, _data);
}
return *this;
}
bool basic_partition_map::operator==(const basic_partition_map &other) const {
if (this->_capacity != other._capacity
|| this->_count != other._count)
return false;
return true;
}
for (size_t i = 0; i < _count; i++)
if (_data[i].name == other._data[i].name
&& _data[i].props.size == other._data[i].props.size
&& _data[i].props.isLogical == other._data[i].props.isLogical)
continue;
else
return false;
bool basic_partition_map::operator!=(const basic_partition_map& other) const
{
return !(*this == other);
}
return true;
}
basic_partition_map::iterator basic_partition_map::begin() const
{
return iterator(_data);
}
bool basic_partition_map::operator!=(const basic_partition_map &other) const {
return !(*this == other);
}
basic_partition_map::iterator basic_partition_map::end() const
{
return iterator(_data + _count);
}
basic_partition_map::iterator basic_partition_map::begin() const {
return iterator(_data);
}
basic_partition_map::constant_iterator basic_partition_map::cbegin() const
{
return constant_iterator(_data);
}
basic_partition_map::iterator basic_partition_map::end() const {
return iterator(_data + _count);
}
basic_partition_map::constant_iterator basic_partition_map::cend() const
{
return constant_iterator(_data + _count);
}
basic_partition_map::constant_iterator basic_partition_map::cbegin() const {
return constant_iterator(_data);
}
basic_partition_map::constant_iterator basic_partition_map::cend() const {
return constant_iterator(_data + _count);
}
} // namespace PartitionMap