libfoedus-core
FOEDUS Core Library
foedus::storage::hash::RecordLocation Struct Reference

return value of locate_record(). More...

Detailed Description

return value of locate_record().

Notes on XID, MOCC Locking, read-set, and "physical_only"
This object also contains observed_, which is guaranteed to be the XID at or before the return from locate_record(). There is a notable contract here. When locking in MOCC kicks in, we want to make sure we return the value of XID after the lock to eliminate a chance of false verification failure. However, this means we need to take lock and register read-set within locate_record(). This caused us headaches for the following reason.
Logical vs Physical search in hash pages
Physically finding a record for given key in our hash page has the following guarantees.
  • When it finds a record, the record was at least at some point a valid (non-moved/non-being-written) record of the given key.
  • When it doesn't find any record, the page(s) at least at some point didn't contain any valid record of the given key.
On the other hand, it still allows the following behaviors:
  • The found record is now being moved or modified.
  • The page or its next page(s) is now newly inserting a physical record of the given key.
Logically finding a record provides additional guarantee to protect against the above at pre-commit time. It additionally takes read-set, page-version set, or even MOCC locks.
locate_record(): Logical or Physical
We initially designed locate_record() as a physical-only search operation separated from logical operations (e.g., get_record/overwrite_record, or the caller). Separation makes each of them simpler and more flexible. The logical side can separately decide, using an operation-specific logic, whether/when it will add the XID observed in locate_record() to read-set or not. The physical side (locate_record()) can be dumb simple, too.

But, seems like this is now unavoidable. Hence now locate_record() is a logical operation. To allow the caller to choose what to do logically, we receive a paramter physical_only. When false, locate_record might take logical lock and add the XID to readset, hence what locate_record() observed is protected. When true, locate_record never takes lock or adds it to readset. It just physically locates a record that was at least at some point a valid record. In this case, the caller is responsible to do appropriate thing to protect from concurrent modifications.

Definition at line 76 of file hash_record_location.hpp.

#include <hash_record_location.hpp>

Collaboration diagram for foedus::storage::hash::RecordLocation:

Public Member Functions

bool is_found () const
 
uint16_t get_aligned_key_length () const
 
uint16_t get_max_payload () const
 
void clear ()
 
ErrorCode populate_logical (xct::Xct *cur_xct, HashDataPage *page, DataPageSlotIndex index, bool intended_for_write)
 Populates the result with XID and possibly readset. More...
 
void populate_physical (HashDataPage *page, DataPageSlotIndex index)
 Populates fields other than readset_. More...
 

Public Attributes

HashDataPagepage_
 The data page (might not be bin-head) containing the record. More...
 
DataPageSlotIndex index_
 Index of the record in the page. More...
 
uint16_t cur_payload_length_
 Logical payload length as-of the observed XID. More...
 
uint16_t key_length_
 Key length of the slot, which is immutable. More...
 
uint16_t physical_record_length_
 Byte count the record of the slot occupies, which is immutable. More...
 
char * record_
 Address of the record. More...
 
xct::XctId observed_
 TID as of locate_record() identifying the record. More...
 
xct::ReadXctAccessreadset_
 If this method took a read-set on the returned record, points to the corresponding read-set. More...
 

Member Function Documentation

void foedus::storage::hash::RecordLocation::clear ( )
inline

Definition at line 114 of file hash_record_location.hpp.

References CXX11_NULLPTR, foedus::xct::XctId::data_, and foedus::storage::hash::kSlotNotFound.

Referenced by foedus::storage::hash::HashStoragePimpl::locate_record(), and foedus::storage::hash::HashStoragePimpl::locate_record_in_snapshot().

114  {
118  key_length_ = 0;
121  observed_.data_ = 0;
123  }
uint16_t physical_record_length_
Byte count the record of the slot occupies, which is immutable.
#define CXX11_NULLPTR
Used in public headers in place of "nullptr" of C++11.
Definition: cxx11.hpp:132
const DataPageSlotIndex kSlotNotFound
Definition: hash_id.hpp:197
HashDataPage * page_
The data page (might not be bin-head) containing the record.
char * record_
Address of the record.
uint16_t key_length_
Key length of the slot, which is immutable.
uint16_t cur_payload_length_
Logical payload length as-of the observed XID.
xct::XctId observed_
TID as of locate_record() identifying the record.
xct::ReadXctAccess * readset_
If this method took a read-set on the returned record, points to the corresponding read-set...
DataPageSlotIndex index_
Index of the record in the page.

Here is the caller graph for this function:

uint16_t foedus::storage::hash::RecordLocation::get_aligned_key_length ( ) const
inline

Definition at line 109 of file hash_record_location.hpp.

References foedus::assorted::align8().

Referenced by get_max_payload(), foedus::storage::hash::HashStoragePimpl::get_record(), foedus::storage::hash::HashStoragePimpl::get_record_part(), and foedus::storage::hash::HashStoragePimpl::increment_record().

109 { return assorted::align8(key_length_); }
T align8(T value)
8-alignment.
uint16_t key_length_
Key length of the slot, which is immutable.

Here is the call graph for this function:

Here is the caller graph for this function:

uint16_t foedus::storage::hash::RecordLocation::get_max_payload ( ) const
inline

Definition at line 110 of file hash_record_location.hpp.

References get_aligned_key_length().

Referenced by foedus::storage::hash::HashStoragePimpl::insert_record(), and foedus::storage::hash::HashStoragePimpl::upsert_record().

110  {
112  }
uint16_t physical_record_length_
Byte count the record of the slot occupies, which is immutable.

Here is the call graph for this function:

Here is the caller graph for this function:

ErrorCode foedus::storage::hash::RecordLocation::populate_logical ( xct::Xct cur_xct,
HashDataPage page,
DataPageSlotIndex  index,
bool  intended_for_write 
)

Populates the result with XID and possibly readset.

This is a logical operation that might take a readset.

Definition at line 27 of file hash_record_location.cpp.

References ASSERT_ND, CHECK_ERROR_CODE, cur_payload_length_, foedus::storage::hash::HashDataPage::get_slot_address(), index_, foedus::xct::XctId::is_being_written(), foedus::xct::XctId::is_moved(), foedus::xct::XctId::is_next_layer(), foedus::xct::XctId::is_valid(), foedus::kErrorCodeOk, key_length_, foedus::storage::hash::HashDataPage::Slot::key_length_, foedus::assorted::memory_fence_consume(), observed_, foedus::storage::hash::HashDataPage::Slot::offset_, foedus::xct::Xct::on_record_read(), page_, foedus::storage::hash::HashDataPage::Slot::payload_length_, physical_record_length_, foedus::storage::hash::HashDataPage::Slot::physical_record_length_, readset_, record_, foedus::storage::hash::HashDataPage::record_from_offset(), foedus::storage::hash::HashDataPage::Slot::tid_, and foedus::xct::RwLockableXctId::xct_id_.

Referenced by foedus::storage::hash::HashStoragePimpl::locate_record().

31  {
32  page_ = page;
33  index_ = index;
34  readset_ = nullptr;
35 
36  HashDataPage::Slot* slot = page->get_slot_address(index);
37  record_ = page->record_from_offset(slot->offset_);
38  key_length_ = slot->key_length_; // key_length is immutable, so just read it.
39  physical_record_length_ = slot->physical_record_length_; // immutable, too.
40 
41  // cur_payload_length_ is mutable, so must be retrieved _as of_ the XID.
42  // we thus need a retry loop.
43  while (true) {
44  xct::XctId before = slot->tid_.xct_id_;
46  cur_payload_length_ = slot->payload_length_;
48 
49  // [Logical check]: Read XID in a finalized fashion. If we found it "moved",
50  // then we don't need to remember it as read-set.
51  CHECK_ERROR_CODE(cur_xct->on_record_read(
52  intended_for_write,
53  &slot->tid_,
54  &observed_,
55  &readset_,
56  true, // no_readset_if_moved. see below
57  true)); // no_readset_if_next_layer. see below
58 
60  ASSERT_ND(!observed_.is_next_layer()); // we don't use this flag in hash. never occurs
62 
63  if (observed_ == before) {
64  // The consume fences make sure we are seeing in this order.
65  // 1. read "before"
66  // 2. read payload_length_
67  // 3. read observed_
68  // thus, observed==before guarantees that payload_length_ is *as of* observed_.
69  break;
70  }
71  }
72 
73  if (observed_.is_moved()) {
74  ASSERT_ND(readset_ == nullptr);
75  }
76  return kErrorCodeOk;
77 }
uint16_t physical_record_length_
Byte count the record of the slot occupies, which is immutable.
bool is_valid() const __attribute__((always_inline))
Definition: xct_id.hpp:973
HashDataPage * page_
The data page (might not be bin-head) containing the record.
char * record_
Address of the record.
0 means no-error.
Definition: error_code.hpp:87
uint16_t key_length_
Key length of the slot, which is immutable.
uint16_t cur_payload_length_
Logical payload length as-of the observed XID.
bool is_next_layer() const __attribute__((always_inline))
Definition: xct_id.hpp:1042
#define CHECK_ERROR_CODE(x)
This macro calls x and checks its returned error code.
Definition: error_code.hpp:155
xct::XctId observed_
TID as of locate_record() identifying the record.
bool is_being_written() const __attribute__((always_inline))
Definition: xct_id.hpp:1038
void memory_fence_consume()
Equivalent to std::atomic_thread_fence(std::memory_order_consume).
xct::ReadXctAccess * readset_
If this method took a read-set on the returned record, points to the corresponding read-set...
bool is_moved() const __attribute__((always_inline))
Definition: xct_id.hpp:1041
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
DataPageSlotIndex index_
Index of the record in the page.

Here is the call graph for this function:

Here is the caller graph for this function:

void foedus::storage::hash::RecordLocation::populate_physical ( HashDataPage page,
DataPageSlotIndex  index 
)

Populates fields other than readset_.

This is a physical-only operation that never takes readset/locks.

Definition at line 79 of file hash_record_location.cpp.

References ASSERT_ND, cur_payload_length_, foedus::storage::hash::HashDataPage::get_slot_address(), index_, foedus::xct::XctId::is_being_written(), foedus::xct::XctId::is_next_layer(), foedus::xct::XctId::is_valid(), key_length_, foedus::storage::hash::HashDataPage::Slot::key_length_, observed_, foedus::storage::hash::HashDataPage::Slot::offset_, page_, foedus::storage::hash::HashDataPage::Slot::payload_length_, physical_record_length_, foedus::storage::hash::HashDataPage::Slot::physical_record_length_, readset_, record_, foedus::storage::hash::HashDataPage::record_from_offset(), foedus::xct::XctId::spin_while_being_written(), foedus::storage::hash::HashDataPage::Slot::tid_, and foedus::xct::RwLockableXctId::xct_id_.

Referenced by foedus::storage::hash::HashStoragePimpl::locate_record(), and foedus::storage::hash::HashStoragePimpl::locate_record_in_snapshot().

79  {
80  page_ = page;
81  index_ = index;
82  readset_ = nullptr;
83 
84  HashDataPage::Slot* slot = page->get_slot_address(index);
85  cur_payload_length_ = slot->payload_length_; // no worry on physical-only read.
86  key_length_ = slot->key_length_;
87  physical_record_length_ = slot->physical_record_length_;
88  record_ = page->record_from_offset(slot->offset_);
89  observed_ = slot->tid_.xct_id_.spin_while_being_written();
91  ASSERT_ND(!observed_.is_next_layer()); // we don't use this flag in hash. never occurs
93 }
uint16_t physical_record_length_
Byte count the record of the slot occupies, which is immutable.
bool is_valid() const __attribute__((always_inline))
Definition: xct_id.hpp:973
HashDataPage * page_
The data page (might not be bin-head) containing the record.
char * record_
Address of the record.
uint16_t key_length_
Key length of the slot, which is immutable.
uint16_t cur_payload_length_
Logical payload length as-of the observed XID.
bool is_next_layer() const __attribute__((always_inline))
Definition: xct_id.hpp:1042
xct::XctId observed_
TID as of locate_record() identifying the record.
bool is_being_written() const __attribute__((always_inline))
Definition: xct_id.hpp:1038
XctId spin_while_being_written() const __attribute__((always_inline))
Returns a version of this Xid whose being_written flag is off.
Definition: xct_id.hpp:1190
xct::ReadXctAccess * readset_
If this method took a read-set on the returned record, points to the corresponding read-set...
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
DataPageSlotIndex index_
Index of the record in the page.

Here is the call graph for this function:

Here is the caller graph for this function:

Member Data Documentation

uint16_t foedus::storage::hash::RecordLocation::cur_payload_length_
uint16_t foedus::storage::hash::RecordLocation::key_length_

Key length of the slot, which is immutable.

Definition at line 88 of file hash_record_location.hpp.

Referenced by populate_logical(), and populate_physical().

xct::XctId foedus::storage::hash::RecordLocation::observed_
uint16_t foedus::storage::hash::RecordLocation::physical_record_length_

Byte count the record of the slot occupies, which is immutable.

Definition at line 90 of file hash_record_location.hpp.

Referenced by populate_logical(), and populate_physical().

xct::ReadXctAccess* foedus::storage::hash::RecordLocation::readset_

If this method took a read-set on the returned record, points to the corresponding read-set.

Otherwise nullptr.

Definition at line 106 of file hash_record_location.hpp.

Referenced by populate_logical(), populate_physical(), and foedus::storage::hash::HashStoragePimpl::register_record_write_log().


The documentation for this struct was generated from the following files: