Revert^2 "Move map_ptr to incfs namspace"
f6a4b40998b6fa71ac08a5fa4c9a9d92fa04b1f0
Change-Id: I6b7d8181c7d68e0da3d6505d3de95269ec7b471b
Merged-In: I6b7d8181c7d68e0da3d6505d3de95269ec7b471b
diff --git a/incfs/tests/util/map_ptr_test.cpp b/incfs/tests/util/map_ptr_test.cpp
index 3ca7fb0..4ed6d0f 100644
--- a/incfs/tests/util/map_ptr_test.cpp
+++ b/incfs/tests/util/map_ptr_test.cpp
@@ -76,8 +76,8 @@
int32_t getReadTimeout() override { return 1; }
- std::unique_ptr<util::IncFsFileMap> GetFileMap(off64_t offset, size_t length) {
- auto map = std::make_unique<util::IncFsFileMap>();
+ std::unique_ptr<IncFsFileMap> GetFileMap(off64_t offset, size_t length) {
+ auto map = std::make_unique<IncFsFileMap>();
return map->Create(fd_, offset, length, nullptr) ? std::move(map) : nullptr;
}
@@ -104,6 +104,22 @@
ASSERT_EQ(1U, p2->second);
}
+TEST_F(MapPtrTest, ReadNull) {
+ auto map = GetFileMap(0U /* offset */, FILE_SIZE);
+ ASSERT_NE(nullptr, map);
+
+ auto p1 = map->data<uint32_t>();
+ ASSERT_TRUE(p1);
+ ASSERT_EQ(0U, p1.value());
+
+ p1 = nullptr;
+ ASSERT_FALSE(p1);
+
+ p1 = map->data<uint32_t>();
+ ASSERT_TRUE(p1);
+ ASSERT_EQ(0U, p1.value());
+}
+
TEST_F(MapPtrTest, ReadAtStartWithOffset) {
auto map = GetFileMap(sizeof(uint32_t) * 4U /* offset */, FILE_SIZE);
ASSERT_NE(nullptr, map);
@@ -183,7 +199,7 @@
auto map = GetFileMap(0U /* offset */, FILE_SIZE);
ASSERT_NE(nullptr, map);
- auto p1 = map->data().offset<TwoValues>(11U * sizeof(uint32_t));
+ auto p1 = map->data().offset(11U * sizeof(uint32_t)).convert<TwoValues>();
ASSERT_TRUE(p1);
ASSERT_EQ(11U, p1->first);
ASSERT_EQ(12U, p1->second);
@@ -245,7 +261,7 @@
ASSERT_NE(nullptr, map);
auto missing_page_start = INCFS_DATA_FILE_BLOCK_SIZE * FILE_MISSING_PAGE;
- auto p1 = map->data().offset<uint32_t>(missing_page_start - off);
+ auto p1 = map->data().offset(missing_page_start - off).convert<uint32_t>();
ASSERT_FALSE(p1);
ASSERT_SIGBUS(p1.value());
@@ -281,7 +297,7 @@
ASSERT_SIGBUS(p6.value());
auto missing_page_end = INCFS_DATA_FILE_BLOCK_SIZE * (FILE_MISSING_PAGE + 1);
- auto p8 = map->data().offset<uint32_t>(missing_page_end - off);
+ auto p8 = map->data().offset(missing_page_end - off).convert<uint32_t>();
ASSERT_TRUE(p8);
ASSERT_EQ(4096U, p8.value());
diff --git a/incfs/util/include/util/map_ptr.h b/incfs/util/include/util/map_ptr.h
index 4f25ead..c5780f9 100644
--- a/incfs/util/include/util/map_ptr.h
+++ b/incfs/util/include/util/map_ptr.h
@@ -30,7 +30,16 @@
class FileMap;
-namespace incfs::util {
+namespace incfs {
+
+// Controls whether not verifying the presence of data before de-referencing the pointer aborts
+// program execution.
+#define LIBINCFS_MAP_PTR_DEBUG false
+#if LIBINCFS_MAP_PTR_DEBUG
+#define LIBINCFS_MAP_PTR_DEBUG_CODE(x) x
+#else
+#define LIBINCFS_MAP_PTR_DEBUG_CODE(x)
+#endif
template <typename T, bool Verified = false>
struct map_ptr;
@@ -43,18 +52,15 @@
//
// This always uses MAP_SHARED.
class IncFsFileMap final {
- // Controls whether not verifying the presence of data before de-referencing the pointer aborts
- // program execution.
- static constexpr bool DEBUG = false;
-
template <typename, bool>
friend struct map_ptr;
-
using bucket_t = uint8_t;
static constexpr size_t kBucketBits = sizeof(bucket_t) * 8U;
public:
IncFsFileMap();
+ IncFsFileMap(IncFsFileMap&&) noexcept;
+ IncFsFileMap& operator =(IncFsFileMap&&) noexcept;
~IncFsFileMap();
// Initializes the map. Does not take ownership of the file descriptor.
@@ -73,6 +79,8 @@
const char* file_name() const;
private:
+ DISALLOW_COPY_AND_ASSIGN(IncFsFileMap);
+
// Returns whether pointers created from this map should run verification of data presence
// to protect against SIGBUS signals.
bool IsVerificationEnabled() const;
@@ -86,7 +94,7 @@
// File descriptor of the memory-mapped file (not owned).
int fd_ = -1;
size_t start_block_offset_ = 0;
- const uint8_t* start_block_ptr_ = 0;
+ const uint8_t* start_block_ptr_ = nullptr;
std::unique_ptr<android::FileMap> map_;
@@ -148,6 +156,12 @@
return safe_ptr_ - other.safe_ptr_;
}
+ const_iterator operator+(int n) const {
+ const_iterator other = *this;
+ other += n;
+ return other;
+ }
+
reference operator*() const { return safe_ptr_; }
const const_iterator& operator++() {
@@ -199,10 +213,10 @@
// Implicit conversion from regular raw pointer
map_ptr& operator=(const T* ptr) {
- map_ = nullptr;
ptr_ = ptr;
+ map_ = nullptr;
verified_block_ = nullptr;
- verified_ = Verified;
+ LIBINCFS_MAP_PTR_DEBUG_CODE(verified_ = Verified);
return *this;
}
@@ -212,10 +226,10 @@
// Copy assignment operator
template <bool V2, bool V1 = Verified, IsUnverified<V1> = 0, IsVerified<V2> = 0>
map_ptr& operator=(const map_ptr<T, V2>& other) {
- map_ = other.map_;
ptr_ = other.ptr_;
+ map_ = other.map_;
verified_block_ = other.verified_block_;
- verified_ = other.verified_;
+ LIBINCFS_MAP_PTR_DEBUG_CODE(verified_ = other.verified_);
return *this;
}
@@ -246,16 +260,15 @@
// Retrieves a map_ptr<T> offset from an original map_ptr<U> by the specified number of `offset`
// bytes.
- template <typename U>
- map_ptr<U> offset(std::ptrdiff_t offset) const {
- return map_ptr<U>(map_,
- reinterpret_cast<const U*>(reinterpret_cast<const uint8_t*>(ptr_) +
+ map_ptr<T> offset(std::ptrdiff_t offset) const {
+ return map_ptr<T>(map_,
+ reinterpret_cast<const T*>(reinterpret_cast<const uint8_t*>(ptr_) +
offset),
verified_block_);
}
// Returns a raw pointer to the value of this pointer.
- const T* unsafe() const { return ptr_; }
+ const T* unsafe_ptr() const { return ptr_; }
// Start T == void methods
@@ -267,19 +280,24 @@
// End T == void methods
// Start T != void methods
+ template <typename T1 = T, NotVoid<T1> = 0, bool V1 = Verified, IsUnverified<V1> = 0>
+ operator bool() const {
+ return verify();
+ }
+
+ template <typename T1 = T, NotVoid<T1> = 0, bool V1 = Verified, IsVerified<V1> = 0>
+ operator bool() const {
+ return ptr_ != nullptr;
+ }
+
template <typename T1 = T, NotVoid<T1> = 0>
const_iterator iterator() const {
return const_iterator(*this);
}
template <typename T1 = T, NotVoid<T1> = 0>
- operator bool() const {
- return Verified ? ptr_ != nullptr : verify() != nullptr;
- }
-
- template <typename T1 = T, NotVoid<T1> = 0>
const map_ptr<T1>& operator++() {
- verified_ = false;
+ LIBINCFS_MAP_PTR_DEBUG_CODE(verified_ = false);
++ptr_;
return *this;
}
@@ -287,7 +305,7 @@
template <typename T1 = T, NotVoid<T1> = 0>
const map_ptr<T1> operator++(int) {
map_ptr<T1> temp = *this;
- verified_ = false;
+ LIBINCFS_MAP_PTR_DEBUG_CODE(verified_ = false);
++ptr_;
return temp;
}
@@ -306,53 +324,56 @@
// The caller should verify the presence of the pointer data before calling this method.
template <typename T1 = T, NotVoid<T1> = 0>
const T1& value() const {
- CHECK(!IncFsFileMap::DEBUG || verified_)
- << "Did not verify presence before de-referencing safe pointer";
+ LIBINCFS_MAP_PTR_DEBUG_CODE(
+ CHECK(verified_) << "Did not verify presence before de-referencing safe pointer");
return *ptr_;
}
// Returns a raw pointer to the value this pointer.
// The caller should verify the presence of the pointer data before calling this method.
template <typename T1 = T, NotVoid<T1> = 0>
- const T1* const& operator->() const {
- CHECK(!IncFsFileMap::DEBUG || verified_)
- << "Did not verify presence before de-referencing safe pointer";
+ const T1* operator->() const {
+ LIBINCFS_MAP_PTR_DEBUG_CODE(
+ CHECK(verified_) << "Did not verify presence before de-referencing safe pointer");
return ptr_;
}
// Verifies the presence of `n` elements of `T`.
//
- // Returns a raw pointer to the value of this pointer if the elements are completely present;
- // otherwise, returns
- // nullptr.
- template <typename N = int, typename T1 = T, NotVoid<T1> = 0>
- const T1* verify(N n = 1) const {
- verified_ = true;
-
+ // Returns true if the elements are completely present; otherwise, returns false.
+ template <typename T1 = T, NotVoid<T1> = 0, bool V1 = Verified, IsUnverified<V1> = 0>
+ bool verify(size_t n = 1) const {
#ifdef __ANDROID__
- if (!map_) {
- return ptr_;
+ if (LIKELY(map_ == nullptr)) {
+ return ptr_ != nullptr;
}
+ if (ptr_ == nullptr) {
+ return false;
+ }
+
+ const size_t verify_size = sizeof(T) * n;
+ LIBINCFS_MAP_PTR_DEBUG_CODE(if (sizeof(T) <= verify_size) verified_ = true;);
+
const auto data_start = reinterpret_cast<const uint8_t*>(ptr_);
- const auto data_end = reinterpret_cast<const uint8_t*>(ptr_ + n);
+ const auto data_end = reinterpret_cast<const uint8_t*>(ptr_) + verify_size;
// If the data is entirely within the block beginning at the previous verified block
// pointer, then the data can safely be used.
if (LIKELY(data_start >= verified_block_ &&
data_end <= verified_block_ + INCFS_DATA_FILE_BLOCK_SIZE)) {
- return ptr_;
+ return true;
}
if (LIKELY(map_->Verify(data_start, data_end, &verified_block_))) {
- return ptr_;
+ return true;
}
- verified_ = false;
- return nullptr;
+ LIBINCFS_MAP_PTR_DEBUG_CODE(verified_ = false);
+ return false;
#else
(void)n;
- return ptr_;
+ return true;
#endif
}
@@ -360,12 +381,9 @@
// The caller should verify the presence of the pointer data before calling this method.
template <typename T1 = T, NotVoid<T1> = 0>
verified_map_ptr<T1> verified() const {
- CHECK(!IncFsFileMap::DEBUG || verified_)
- << "Did not verify presence before de-referencing safe pointer";
return verified_map_ptr<T1>(map_, ptr_, verified_block_);
}
- // End T != void type methods
private:
map_ptr(const IncFsFileMap* map, const T* ptr)
: ptr_(ptr), map_(map), verified_block_(nullptr) {}
@@ -375,9 +393,9 @@
const T* ptr_ = nullptr;
mutable const IncFsFileMap* map_ = nullptr;
mutable const uint8_t* verified_block_;
- mutable bool verified_ = Verified;
+ LIBINCFS_MAP_PTR_DEBUG_CODE(mutable bool verified_ = Verified);
};
-} // namespace incfs::util
+} // namespace incfs
} // namespace android
\ No newline at end of file
diff --git a/incfs/util/map_ptr.cpp b/incfs/util/map_ptr.cpp
index f32bc89..7b0310e 100644
--- a/incfs/util/map_ptr.cpp
+++ b/incfs/util/map_ptr.cpp
@@ -24,9 +24,11 @@
#include "util/map_ptr.h"
-namespace android::incfs::util {
+namespace android::incfs {
IncFsFileMap::IncFsFileMap() = default;
+IncFsFileMap::IncFsFileMap(IncFsFileMap&&) noexcept = default;
+IncFsFileMap& IncFsFileMap::operator =(IncFsFileMap&&) noexcept = default;
IncFsFileMap::~IncFsFileMap() = default;
const void* IncFsFileMap::unsafe_data() const {
@@ -96,7 +98,7 @@
// safely.
for (data_block_index_t curr_index = start_index; curr_index <= end_index; ++curr_index) {
const size_t i = curr_index / kBucketBits;
- const auto present_bit = 1U << (curr_index % kBucketBits);
+ const bucket_t present_bit = 1U << (curr_index % kBucketBits);
std::atomic<bucket_t>& bucket = loaded_blocks_[i];
if (LIKELY(bucket.load(std::memory_order_relaxed) & present_bit)) {
continue;
@@ -105,7 +107,7 @@
// Touch all of the blocks with pread to ensure that the region of data is fully present.
uint8_t value;
const off64_t read_offset = (curr_index * INCFS_DATA_FILE_BLOCK_SIZE) + start_block_offset_;
- if (UNLIKELY(!android::base::ReadFullyAtOffset(fd_, &value, 1U, read_offset))) {
+ if (UNLIKELY(TEMP_FAILURE_RETRY(pread64(fd_, &value, 1U, read_offset)) <= 0)) {
success = false;
break;
}
@@ -132,4 +134,4 @@
}
#endif
-} // namespace android::incfs::util
\ No newline at end of file
+} // namespace android::incfs
\ No newline at end of file