16 #ifndef PSTORE_MCREPO_FRAGMENT_HPP 17 #define PSTORE_MCREPO_FRAGMENT_HPP 19 #include "pstore/mcrepo/bss_section.hpp" 23 #include "pstore/support/pointee_adaptor.hpp" 32 template <
typename Iterator>
35 using value_type = section_kind
const;
36 using difference_type =
typename std::iterator_traits<Iterator>::difference_type;
37 using pointer = value_type *;
38 using reference = value_type &;
39 using iterator_category = std::input_iterator_tag;
52 return !(operator== (rhs));
59 auto const old = *
this;
64 reference operator* ()
const {
return (*it_).kind (); }
65 pointer operator-> ()
const {
return &(*it_).kind (); }
66 reference operator[] (difference_type n)
const {
return it_[n].kind (); }
72 template <
typename Iterator>
82 template <section_kind T>
86 template <section_kind T>
111 using const_iterator = member_array::indices::const_iterator;
125 template <
typename Transaction,
typename Iterator>
135 static std::shared_ptr<fragment const> load (
database const & db,
153 return arr_.has_index (kind);
161 template <section_kind Key>
163 return at_impl<Key> (*this);
167 template <section_kind Key>
169 return at_impl<Key> (*this);
174 template <section_kind Key>
176 return atp_impl<Key> (*this);
180 template <section_kind Key>
182 return atp_impl<Key> (*this);
187 std::size_t
size () const noexcept {
return arr_.size (); }
192 section_kind front ()
const noexcept {
return arr_.get_indices ().front (); }
194 const_iterator
begin ()
const noexcept {
return arr_.get_indices ().begin (); }
195 const_iterator end ()
const noexcept {
return arr_.get_indices ().end (); }
205 template <
typename Iterator>
206 static std::size_t size_bytes (Iterator first, Iterator last);
209 std::size_t size_bytes ()
const;
212 template <
typename IteratorIdx>
213 constexpr
fragment (IteratorIdx
const first_index, IteratorIdx
const last_index)
214 : arr_{first_index, last_index} {
218 PSTORE_STATIC_ASSERT (
alignof (fragment) == 16);
219 PSTORE_STATIC_ASSERT (
sizeof (fragment) == 32);
220 PSTORE_STATIC_ASSERT (offsetof (fragment, signature_) == 0);
221 PSTORE_STATIC_ASSERT (offsetof (fragment, padding1_) == 8);
222 PSTORE_STATIC_ASSERT (offsetof (fragment, arr_) == 16);
228 template <
typename ReturnType,
typename GetOp>
231 template <
typename Iterator>
232 static void check_range_is_sorted (Iterator first, Iterator last);
239 template <
typename InstanceType>
240 InstanceType
const & offset_to_instance (std::uint64_t offset)
const noexcept {
241 return offset_to_instance_impl<InstanceType const> (*
this, offset);
243 template <
typename InstanceType>
244 InstanceType & offset_to_instance (std::uint64_t offset) noexcept {
245 return offset_to_instance_impl<InstanceType> (*
this, offset);
252 template <
typename InstanceType,
typename Fragment>
253 static InstanceType & offset_to_instance_impl (Fragment && f,
254 std::uint64_t offset) noexcept;
256 template <section_kind Key, typename InstanceType = typename enum_to_section<Key>::type>
257 static std::uint64_t section_offset_is_valid (fragment
const & f,
259 std::uint64_t min_offset,
260 std::uint64_t offset, std::size_t size);
263 static bool fragment_appears_valid (fragment
const & f,
extent<fragment> const & fext);
274 template <section_kind Key,
typename Fragment,
277 static ResultType & at_impl (Fragment && f) noexcept {
279 return f.template offset_to_instance<ResultType> (f.arr_[Key]);
291 template <section_kind Key,
typename Fragment,
294 static ResultType * atp_impl (Fragment && f) noexcept {
295 return f.
has_section (Key) ? &f.template at<Key> () :
nullptr;
308 template <
typename Iterator>
309 static void populate (
void * ptr, Iterator first, Iterator last);
311 static constexpr std::array<char, 8> fragment_signature_ = {
312 {
'F',
'r',
'a',
'g',
'm',
'e',
'n',
't'}};
314 std::array<char, 8> signature_ = fragment_signature_;
315 std::uint64_t padding1_ = 0;
325 template <
typename OStream>
326 OStream & operator<< (OStream & os, section_kind
const kind) {
327 auto * name =
"*unknown*";
329 case section_kind::k: name = #k; break; 331 PSTORE_MCREPO_SECTION_KINDS
332 case section_kind::last: PSTORE_ASSERT (
false);
break;
341 template <
typename Iterator>
342 void fragment::populate (
void *
const ptr, Iterator
const first, Iterator
const last) {
344 auto *
const fragment_ptr =
345 new (ptr)
fragment (details::make_content_type_iterator (first),
346 details::make_content_type_iterator (last));
348 auto * out =
reinterpret_cast<std::uint8_t *
> (fragment_ptr) +
354 out =
reinterpret_cast<std::uint8_t *
> (c.
aligned (out));
355 fragment_ptr->arr_[c.kind ()] =
reinterpret_cast<std::uintptr_t
> (out) -
356 reinterpret_cast<std::uintptr_t> (fragment_ptr);
362 PSTORE_ASSERT (out >= ptr &&
363 static_cast<std::size_t> (
364 out - reinterpret_cast<std::uint8_t *> (ptr)) == size);
365 PSTORE_ASSERT (size == fragment_ptr->size_bytes ());
372 template <
typename Transaction,
typename Iterator>
375 fragment::check_range_is_sorted (first, last);
383 transaction.alloc_rw (size,
alignof (
fragment));
384 fragment::populate (storage.first.get (), first, last);
391 template <
typename ReturnType,
typename GetOp>
392 auto fragment::load_impl (
extent<fragment> const & fext, GetOp
get) -> ReturnType {
394 raise (error_code::bad_fragment_record);
397 ReturnType f =
get (fext);
398 if (!fragment::fragment_appears_valid (*f, fext)) {
399 raise (error_code::bad_fragment_record);
408 -> std::shared_ptr<fragment> {
409 return load_impl<std::shared_ptr<fragment>> (
411 [&transaction] (
extent<fragment> const & x) {
return transaction.getrw (x); });
419 template <
typename InstanceType,
typename Fragment>
420 inline InstanceType & fragment::offset_to_instance_impl (Fragment && f,
421 std::uint64_t offset) noexcept {
422 return *
reinterpret_cast<InstanceType *
> (
429 template <
typename Iterator>
430 void fragment::check_range_is_sorted (Iterator first, Iterator last) {
434 using value_type =
typename std::iterator_traits<Iterator>::value_type;
436 std::is_sorted (first, last, [] (value_type
const & a, value_type
const & b) {
437 section_kind
const akind = a.kind ();
438 section_kind
const bkind = b.kind ();
439 using utype = std::underlying_type<section_kind>::type;
440 return static_cast<utype
> (akind) < static_cast<utype> (bkind);
447 template <
typename Iterator>
449 fragment::check_range_is_sorted (first, last);
451 auto const num_contents = std::distance (first, last);
452 PSTORE_ASSERT (num_contents >= 0);
453 auto const unum_contents =
454 static_cast<typename std::make_unsigned<decltype (num_contents)>::type
> (
458 std::size_t size_bytes =
459 offsetof (
fragment, arr_) + decltype (fragment::arr_)::size_bytes (unum_contents);
462 size_bytes = c.
aligned (size_bytes);
474 std::size_t section_size (fragment
const & fragment, section_kind kind);
487 #endif // PSTORE_MCREPO_FRAGMENT_HPP Contains declarations for the "linked-definition" section type.
bool has_section(section_kind const kind) const noexcept
Returns true if the fragment contains a section of the kind given by kind, false otherwise.
Definition: fragment.hpp:152
auto atp() noexcept -> typename enum_to_section< Key >::type *
Returns a pointer to the section data given the section kind or nullptr if the section is not present...
Definition: fragment.hpp:181
An extent is a contiguous area of storage reserved for a data BLOB, represented as a range...
Definition: address.hpp:441
auto at() const noexcept -> typename enum_to_section< Key >::type const &
Returns a const reference to the section data given the section kind.
Definition: fragment.hpp:162
Definition: address.hpp:81
A simple wrapper around the elements of one of the three arrays that make up a section.
Definition: section.hpp:152
Definition: debug_line_section.hpp:38
member_array const & members() const noexcept
Returns the array of section offsets.
Definition: fragment.hpp:190
auto at() noexcept -> typename enum_to_section< Key >::type &
Returns a reference to the section data given the section kind.
Definition: fragment.hpp:168
transaction< transaction_lock > begin(database &db, transaction_lock &lock)
Creates a new transaction. Every operation performed on a transaction instance can be potentially und...
Definition: transaction.hpp:311
Definition: fragment.hpp:107
Definition: transaction.hpp:191
Definition: address.hpp:231
Definition: generic_section.hpp:177
static constexpr std::size_t size_bytes(std::size_t members) noexcept
Returns the number of bytes of storage that are required for an instance of section_sparray<T> where ...
Definition: section_sparray.hpp:280
Definition: bss_section.hpp:31
Maps from the section kind enumeration to the type that is used to represent a section of that kind...
Definition: fragment.hpp:83
std::uint64_t size
The size of the data associated with this extent.
Definition: address.hpp:461
Represents the definitions linked to a fragment.
Definition: linked_definitions_section.hpp:62
An iterator adaptor which produces a value_type of 'section_kind const' from values deferenced from t...
Definition: fragment.hpp:33
Definition: storage.hpp:58
Definition: nonpod2.cpp:40
Definition: database.hpp:40
A wrapper for sparse_array<> which accepts indices of type section_kind.
Provides a member typedef inherit_const::type, which is defined as R const if T is a const type and R...
Definition: inherit_const.hpp:108
std::size_t size() const noexcept
Return the number of sections in the fragment.
Definition: fragment.hpp:187
static pstore::extent< fragment > alloc(Transaction &transaction, Iterator first, Iterator last)
Prepares an instance of a fragment with the collection of sections defined by the iterator range [fir...
std::size_t size_bytes() const
Returns the number of bytes of storage that are accupied by this fragment.
Definition: fragment.cpp:164
virtual std::size_t size_bytes() const =0
Returns the number of bytes of storage that are required for an instance of the section data...
virtual std::uint8_t * write(std::uint8_t *out) const =0
Copies the section instance data to the memory starting at out.
A section creation dispatcher is used to instantiate and construct each of a fragment's sections in p...
Definition: section.hpp:91
std::size_t aligned(IntType a) const
Definition: section.hpp:108
static std::shared_ptr< fragment const > load(database const &db, extent< fragment > const &location)
Provides a pointer to an individual fragment instance given a database and a extent describing its ad...
Definition: fragment.cpp:94
typename std::conditional< std::is_const< typename std::remove_reference< T >::type >::value, RC, R >::type type
If T is const, R const otherwise R.
Definition: inherit_const.hpp:112
auto atp() const noexcept -> typename enum_to_section< Key >::type const *
Returns a pointer to the section data given the section kind or nullptr if the section is not present...
Definition: fragment.hpp:175
Declares the type used to record debug_line sections in a fragment.
The database transaction class.
Definition: transaction.hpp:43