libfoedus-core
FOEDUS Core Library
foedus::storage::masstree::MasstreeCursor Class Referencefinal

Represents a cursor object for Masstree storage. More...

Detailed Description

Represents a cursor object for Masstree storage.

Cursor Example
Below is a typical usecase (from TPC-C) of this cursor class.
... (begin xct, etc)
MasstreeCursor cursor(orderlines, context);
CHECK_ERROR_CODE(cursor.open_normalized(low, high, true, true));
while (cursor.is_valid_record()) {
const char* key_be = cursor.get_key();
const OrderlineData* payload = reinterpret_cast<const OrderlineData*>(cursor.get_payload());
*ol_amount_total += payload->amount_;
++(*ol_count);
CHECK_ERROR_CODE(cursor.overwrite_record(delivery_date, offset, delivery_date_len));
CHECK_ERROR_CODE(cursor.next());
}
... (commit xct, etc)
Dynamic Memory
This cursor objects uses a few dymanically allocated memory for keys, route information, etc. However, we of course can't tolerate new/delete during transaction. We thus grab memory from the memory pool for snapshot pages (could be volatile page's, but probably volatile memory pool is more limiting, so let's grab it from snapshot memory pool). These memory are allocated via libnuma and using THP, so it's also faster. The only drawback is that we consume them in a little bit generous way, but shouldn't be a big issue. All of them are returned to the pool in destructor.

Definition at line 75 of file masstree_cursor.hpp.

#include <masstree_cursor.hpp>

Classes

struct  Route
 Represents one page in the current search path from layer0-root. More...
 

Public Types

enum  SearchType { kForwardInclusive = 0, kForwardExclusive, kBackwardInclusive, kBackwardExclusive }
 
enum  KeyCompareResult {
  kCurKeySmaller, kCurKeyEquals, kCurKeyLarger, kCurKeyBeingsWith,
  kCurKeyContains
}
 
enum  Constants { kMaxRecords = kBorderPageMaxSlots, kMaxRoutes = kPageSize / sizeof(Route), kKeyLengthExtremum = 0 }
 

Public Member Functions

 MasstreeCursor (MasstreeStorage storage, thread::Thread *context)
 
thread::Threadget_context ()
 
MasstreeStorageget_storage ()
 
bool is_for_writes () const
 
bool is_forward_cursor () const
 
ErrorCode open (const char *begin_key=nullptr, KeyLength begin_key_length=kKeyLengthExtremum, const char *end_key=nullptr, KeyLength end_key_length=kKeyLengthExtremum, bool forward_cursor=true, bool for_writes=false, bool begin_inclusive=true, bool end_inclusive=false)
 
ErrorCode open_normalized (KeySlice begin_key, KeySlice end_key, bool forward_cursor=true, bool for_writes=false, bool begin_inclusive=true, bool end_inclusive=false)
 
bool is_valid_record () const __attribute__((always_inline))
 
KeyLength get_key_length () const __attribute__((always_inline))
 Returns the length of the whole key we are currently pointing to. More...
 
const KeySliceget_cur_route_prefix_slices () const __attribute__((always_inline))
 Returns the prefix slices upto the current page. More...
 
const char * get_cur_route_prefix_be () const __attribute__((always_inline))
 Big-endian version. More...
 
KeySlice get_key_in_layer_slice () const __attribute__((always_inline))
 Returns only the slice of the key in the layer of the current page. More...
 
const char * get_key_suffix () const __attribute__((always_inline))
 Returns the suffix part of the key in the page. More...
 
KeySlice get_normalized_key () const __attribute__((always_inline))
 This method assumes the key length is at most 8 bytes. More...
 
void copy_combined_key (char *buffer) const
 Copies the entire big-endian key of the current record to the given buffer. More...
 
void copy_combined_key_part (KeyLength offset, KeyLength len, char *buffer) const
 Another version to get a part of the key, from the offset for len bytes. More...
 
std::string get_combined_key () const __attribute__((always_inline))
 For even handier use, it returns std::string. More...
 
const char * get_payload () const __attribute__((always_inline))
 
PayloadLength get_payload_length () const __attribute__((always_inline))
 
ErrorCode next ()
 Moves the cursor to next record. More...
 
ErrorCode delete_record ()
 
ErrorCode overwrite_record (const void *payload, PayloadLength payload_offset, PayloadLength payload_count)
 
template<typename PAYLOAD >
ErrorCode overwrite_record_primitive (PAYLOAD payload, PayloadLength payload_offset)
 
template<typename PAYLOAD >
ErrorCode increment_record (PAYLOAD *value, PayloadLength payload_offset)
 

Member Enumeration Documentation

Enumerator
kMaxRecords 
kMaxRoutes 
kKeyLengthExtremum 

Definition at line 178 of file masstree_cursor.hpp.

178  {
180  kMaxRoutes = kPageSize / sizeof(Route),
181  kKeyLengthExtremum = 0,
182  };
const SlotIndex kBorderPageMaxSlots
Maximum number of slots in one MasstreeBorderPage.
const uint16_t kPageSize
A constant defining the page size (in bytes) of both snapshot pages and volatile pages.
Definition: storage_id.hpp:45

Constructor & Destructor Documentation

foedus::storage::masstree::MasstreeCursor::MasstreeCursor ( MasstreeStorage  storage,
thread::Thread context 
)

Definition at line 41 of file masstree_cursor.cpp.

References foedus::storage::masstree::RecordLocation::clear().

42  : engine_(storage.get_engine()),
43  storage_(storage.get_engine(), storage.get_control_block()),
44  context_(context),
45  current_xct_(&context->get_current_xct()) {
46  for_writes_ = false;
47  forward_cursor_ = true;
48  reached_end_ = false;
49 
50  route_count_ = 0;
51  routes_ = nullptr;
52  should_skip_cur_route_ = false;
53 
54  end_inclusive_ = false;
55  end_key_length_ = 0;
56  end_key_ = nullptr;
57  end_key_slices_ = nullptr;
58 
59  cur_route_prefix_slices_ = nullptr;
60  cur_route_prefix_be_ = nullptr;
61 
62  cur_key_length_ = 0;
63  cur_key_owner_id_address = nullptr;
64  cur_key_suffix_ = nullptr;
65  cur_key_in_layer_slice_ = 0;
66  cur_key_in_layer_remainder_ = 0;
67  cur_key_next_layer_ = false;
68  cur_key_location_.clear();
69 
70  cur_payload_length_ = 0;
71 
72  search_key_length_ = 0;
73  search_key_ = nullptr;
74  search_key_slices_ = nullptr;
75 }

Here is the call graph for this function:

Member Function Documentation

void foedus::storage::masstree::MasstreeCursor::copy_combined_key ( char *  buffer) const

Copies the entire big-endian key of the current record to the given buffer.

Parameters
[out]bufferto receive the combined big-endian key. must be get_key_length() or longer.

In other words, this combines get_cur_route_prefixes(), get_key_in_layer_slice() and get_key_suffix(). This method is handy to get a whole key as one char array, but it must copy something, so remember that it's a bit costly.

Why we can't just return const char*
We initially provided such a method "get_key()". However, to provide such a method, we have to keep memcpy-ing for each key because there is no single contiguous key string! A key in masstree is stored in at least 3 components; prefix slices, current slice, suffix. If we could just point to somewhere in the data page, it's a no-cost operation. What we can do is only get_key_suffix() in that regard. We removed the get_key() method and instead added this explicit copy-method so that the user can choose when to re-construct the entire key.

Definition at line 77 of file masstree_cursor.cpp.

References ASSERT_ND, ASSUME_ALIGNED, foedus::storage::masstree::calculate_suffix_length(), foedus::storage::masstree::MasstreePage::get_layer(), is_valid_record(), foedus::storage::masstree::kInitiallyNextLayer, foedus::storage::masstree::MasstreeCursor::Route::layer_, and foedus::storage::masstree::MasstreeCursor::Route::page_.

Referenced by delete_record(), get_combined_key(), increment_record(), overwrite_record(), and overwrite_record_primitive().

77  {
79  const Route* route = cur_route();
80  const Layer layer = route->layer_;
81  ASSERT_ND(layer == route->page_->get_layer());
82  ASSERT_ND(cur_key_in_layer_remainder_ != kInitiallyNextLayer);
83  ASSERT_ND(cur_key_length_ == cur_key_in_layer_remainder_ + layer * sizeof(KeySlice));
84 
85  std::memcpy(buffer, ASSUME_ALIGNED(cur_route_prefix_be_, 256), layer * sizeof(KeySlice));
86  assorted::write_bigendian<KeySlice>(cur_key_in_layer_slice_, buffer + layer * sizeof(KeySlice));
87  KeyLength suffix_length = calculate_suffix_length(cur_key_in_layer_remainder_);
88  if (suffix_length > 0) {
89  std::memcpy(
90  buffer + (layer + 1U) * sizeof(KeySlice),
91  ASSUME_ALIGNED(cur_key_suffix_, 8),
92  suffix_length);
93  }
94 }
uint64_t KeySlice
Each key slice is an 8-byte integer.
uint16_t KeyLength
Represents a byte-length of a key in this package.
Definition: masstree_id.hpp:69
#define ASSUME_ALIGNED(x, y)
Wraps GCC's __builtin_assume_aligned.
Definition: compiler.hpp:111
uint8_t Layer
Represents the depth of a B-trie layer.
Definition: masstree_id.hpp:42
bool is_valid_record() const __attribute__((always_inline))
const KeyLength kInitiallyNextLayer
A special key length value that denotes the record in a border page was initially a next-layer pointe...
Definition: masstree_id.hpp:86
KeyLength calculate_suffix_length(KeyLength remainder_length) __attribute__((always_inline))
#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

Here is the call graph for this function:

Here is the caller graph for this function:

void foedus::storage::masstree::MasstreeCursor::copy_combined_key_part ( KeyLength  offset,
KeyLength  len,
char *  buffer 
) const

Another version to get a part of the key, from the offset for len bytes.

Definition at line 95 of file masstree_cursor.cpp.

References ASSERT_ND, foedus::storage::masstree::calculate_suffix_length(), foedus::storage::masstree::MasstreePage::get_layer(), is_valid_record(), foedus::storage::masstree::kInitiallyNextLayer, foedus::storage::masstree::MasstreeCursor::Route::layer_, and foedus::storage::masstree::MasstreeCursor::Route::page_.

95  {
97  ASSERT_ND(offset + len <= cur_key_length_);
98  const Route* route = cur_route();
99  const Layer layer = route->layer_;
100  ASSERT_ND(layer == route->page_->get_layer());
101  ASSERT_ND(cur_key_in_layer_remainder_ != kInitiallyNextLayer);
102  ASSERT_ND(cur_key_length_ == cur_key_in_layer_remainder_ + layer * sizeof(KeySlice));
103 
104  const KeyLength prefix_len = layer * sizeof(KeySlice);
105  KeyLength buffer_pos = 0;
106  KeyLength len_remaining = len;
107  if (offset < prefix_len) {
108  KeyLength prefix_copy_len = std::min<KeyLength>(prefix_len - offset, len_remaining);
109  std::memcpy(buffer, cur_route_prefix_be_ + offset, prefix_copy_len);
110  buffer_pos += prefix_copy_len;
111  len_remaining -= prefix_copy_len;
112  }
113 
114  if (len_remaining > 0) {
115  if (offset < prefix_len + sizeof(KeySlice)) {
116  char cur_slice_be[sizeof(KeySlice)];
117  assorted::write_bigendian<KeySlice>(cur_key_in_layer_slice_, cur_slice_be);
118 
119  KeyLength cur_slice_offset = offset - prefix_len;
120  KeyLength cur_slice_copy_len
121  = std::min<KeyLength>(sizeof(KeySlice) - cur_slice_offset, len_remaining);
122  std::memcpy(buffer + buffer_pos, cur_slice_be + cur_slice_offset, cur_slice_copy_len);
123  buffer_pos += cur_slice_copy_len;
124  len_remaining -= cur_slice_copy_len;
125  }
126 
127  if (len_remaining > 0) {
128  KeyLength suffix_offset = offset - prefix_len - sizeof(KeySlice);
129  KeyLength suffix_length = calculate_suffix_length(cur_key_in_layer_remainder_);
130  KeyLength suffix_copy_len = std::min<KeyLength>(suffix_length - suffix_offset, len_remaining);
131  std::memcpy(
132  buffer + buffer_pos,
133  cur_key_suffix_ + suffix_offset,
134  suffix_copy_len);
135  buffer_pos += suffix_copy_len;
136  len_remaining -= suffix_copy_len;
137  }
138  }
139 
140  ASSERT_ND(buffer_pos == len);
141  ASSERT_ND(len_remaining == 0);
142 }
uint64_t KeySlice
Each key slice is an 8-byte integer.
uint16_t KeyLength
Represents a byte-length of a key in this package.
Definition: masstree_id.hpp:69
uint8_t Layer
Represents the depth of a B-trie layer.
Definition: masstree_id.hpp:42
bool is_valid_record() const __attribute__((always_inline))
const KeyLength kInitiallyNextLayer
A special key length value that denotes the record in a border page was initially a next-layer pointe...
Definition: masstree_id.hpp:86
KeyLength calculate_suffix_length(KeyLength remainder_length) __attribute__((always_inline))
#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

Here is the call graph for this function:

ErrorCode foedus::storage::masstree::MasstreeCursor::delete_record ( )

Definition at line 1305 of file masstree_cursor.cpp.

References copy_combined_key(), foedus::storage::masstree::MasstreeStoragePimpl::delete_general(), and foedus::storage::masstree::kMaxKeyLength.

1305  {
1306  assert_modify();
1307  char key[kMaxKeyLength];
1308  copy_combined_key(key);
1309  return MasstreeStoragePimpl(&storage_).delete_general(
1310  context_,
1311  cur_key_location_,
1312  key,
1313  cur_key_length_);
1314 }
const KeyLength kMaxKeyLength
Max length of a key.
Definition: masstree_id.hpp:75
void copy_combined_key(char *buffer) const
Copies the entire big-endian key of the current record to the given buffer.

Here is the call graph for this function:

std::string foedus::storage::masstree::MasstreeCursor::get_combined_key ( ) const
inline

For even handier use, it returns std::string.

It's SLOOOW. So use it as such.

Definition at line 280 of file masstree_cursor.hpp.

References copy_combined_key(), and foedus::storage::masstree::kMaxKeyLength.

280  {
281  char buf[kMaxKeyLength];
282  copy_combined_key(buf);
283  return std::string(buf, cur_key_length_);
284  }
const KeyLength kMaxKeyLength
Max length of a key.
Definition: masstree_id.hpp:75
void copy_combined_key(char *buffer) const
Copies the entire big-endian key of the current record to the given buffer.

Here is the call graph for this function:

thread::Thread* foedus::storage::masstree::MasstreeCursor::get_context ( )
inline

Definition at line 186 of file masstree_cursor.hpp.

186 { return context_; }
const char* foedus::storage::masstree::MasstreeCursor::get_cur_route_prefix_be ( ) const
inline

Big-endian version.

Definition at line 239 of file masstree_cursor.hpp.

239  {
240  return cur_route_prefix_be_;
241  }
const KeySlice* foedus::storage::masstree::MasstreeCursor::get_cur_route_prefix_slices ( ) const
inline

Returns the prefix slices upto the current page.

When the current page is in layer-n, first n slices are set.

Definition at line 235 of file masstree_cursor.hpp.

235  {
236  return cur_route_prefix_slices_;
237  }
KeySlice foedus::storage::masstree::MasstreeCursor::get_key_in_layer_slice ( ) const
inline

Returns only the slice of the key in the layer of the current page.

Mostly internal use

Definition at line 243 of file masstree_cursor.hpp.

References ASSERT_ND, and is_valid_record().

243  {
245  return cur_key_in_layer_slice_;
246  }
bool is_valid_record() const __attribute__((always_inline))
#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

Here is the call graph for this function:

KeyLength foedus::storage::masstree::MasstreeCursor::get_key_length ( ) const
inline

Returns the length of the whole key we are currently pointing to.

Definition at line 227 of file masstree_cursor.hpp.

References ASSERT_ND, and is_valid_record().

227  {
229  return cur_key_length_;
230  }
bool is_valid_record() const __attribute__((always_inline))
#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

Here is the call graph for this function:

const char* foedus::storage::masstree::MasstreeCursor::get_key_suffix ( ) const
inline

Returns the suffix part of the key in the page.

Mostly internal use

Definition at line 248 of file masstree_cursor.hpp.

References ASSERT_ND, and is_valid_record().

248  {
250  return cur_key_suffix_;
251  }
bool is_valid_record() const __attribute__((always_inline))
#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

Here is the call graph for this function:

KeySlice foedus::storage::masstree::MasstreeCursor::get_normalized_key ( ) const
inline

This method assumes the key length is at most 8 bytes.

Instead, it's fast and handy.

Definition at line 253 of file masstree_cursor.hpp.

References ASSERT_ND, and is_valid_record().

253  {
255  ASSERT_ND(cur_key_length_ <= sizeof(KeySlice));
256  return cur_key_in_layer_slice_;
257  };
uint64_t KeySlice
Each key slice is an 8-byte integer.
bool is_valid_record() const __attribute__((always_inline))
#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

Here is the call graph for this function:

const char* foedus::storage::masstree::MasstreeCursor::get_payload ( ) const
inline

Definition at line 286 of file masstree_cursor.hpp.

References ASSERT_ND, and is_valid_record().

286  {
288  return cur_payload_;
289  }
bool is_valid_record() const __attribute__((always_inline))
#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

Here is the call graph for this function:

PayloadLength foedus::storage::masstree::MasstreeCursor::get_payload_length ( ) const
inline

Definition at line 290 of file masstree_cursor.hpp.

References ASSERT_ND, and is_valid_record().

290  {
292  return cur_payload_length_;
293  }
bool is_valid_record() const __attribute__((always_inline))
#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

Here is the call graph for this function:

MasstreeStorage& foedus::storage::masstree::MasstreeCursor::get_storage ( )
inline

Definition at line 187 of file masstree_cursor.hpp.

187 { return storage_; }
template<typename PAYLOAD >
ErrorCode foedus::storage::masstree::MasstreeCursor::increment_record ( PAYLOAD *  value,
PayloadLength  payload_offset 
)

Definition at line 1317 of file masstree_cursor.cpp.

References copy_combined_key(), foedus::storage::masstree::MasstreeStoragePimpl::increment_general(), and foedus::storage::masstree::kMaxKeyLength.

1317  {
1318  assert_modify();
1319  char key[kMaxKeyLength];
1320  copy_combined_key(key);
1321  return MasstreeStoragePimpl(&storage_).increment_general<PAYLOAD>(
1322  context_,
1323  cur_key_location_,
1324  key,
1325  cur_key_length_,
1326  value,
1327  payload_offset);
1328 }
const KeyLength kMaxKeyLength
Max length of a key.
Definition: masstree_id.hpp:75
void copy_combined_key(char *buffer) const
Copies the entire big-endian key of the current record to the given buffer.

Here is the call graph for this function:

bool foedus::storage::masstree::MasstreeCursor::is_for_writes ( ) const
inline

Definition at line 188 of file masstree_cursor.hpp.

188 { return for_writes_; }
bool foedus::storage::masstree::MasstreeCursor::is_forward_cursor ( ) const
inline

Definition at line 189 of file masstree_cursor.hpp.

189 { return forward_cursor_; }
bool foedus::storage::masstree::MasstreeCursor::is_valid_record ( ) const
inline

Definition at line 223 of file masstree_cursor.hpp.

References foedus::storage::masstree::MasstreeCursor::Route::is_valid_record().

Referenced by copy_combined_key(), copy_combined_key_part(), get_key_in_layer_slice(), get_key_length(), get_key_suffix(), get_normalized_key(), get_payload(), get_payload_length(), next(), and open().

223  {
224  return route_count_ > 0 && !reached_end_ && cur_route()->is_valid_record();
225  }
bool is_valid_record() const __attribute__((always_inline))

Here is the call graph for this function:

Here is the caller graph for this function:

ErrorCode foedus::storage::masstree::MasstreeCursor::next ( )

Moves the cursor to next record.

When the cursor already reached the end, it does nothing.

Implementation note
This method changes a complete state of the cursor to a next complete status. In other words, this must NOT be called from other internal methods when this object is in interim state (such as should_skip_cur_route_==true). When this method returns, it is guaranteed that should_skip_cur_route_==false for this reason.

Definition at line 174 of file masstree_cursor.cpp.

References ASSERT_ND, CHECK_ERROR_CODE, foedus::xct::XctId::is_deleted(), is_valid_record(), foedus::kErrorCodeOk, and foedus::storage::masstree::RecordLocation::observed_.

174  {
175  ASSERT_ND(!should_skip_cur_route_);
176  if (!is_valid_record()) {
177  return kErrorCodeOk;
178  }
179 
180  assert_route();
181 
182  CHECK_ERROR_CODE(proceed_route());
183 
184  // After proceed_route(), it is still possible that we are at a deleted record or empty page.
185  // Keep moving on in that case.
186  while (should_skip_cur_route_
187  || (is_valid_record() && cur_key_location_.observed_.is_deleted())) {
188  DVLOG(0) << "Rare. next() needs to move on to find non-deleted records/pages";
189  should_skip_cur_route_ = false;
190  CHECK_ERROR_CODE(proceed_route());
191  if (route_count_ == 0) {
192  LOG(INFO) << "The empty page was the last page that might have had the record. we are done";
194  return kErrorCodeOk;
195  }
196  }
197  ASSERT_ND(!should_skip_cur_route_);
198  check_end_key();
199  if (is_valid_record()) {
200  assert_route();
201  ASSERT_ND(!cur_key_location_.observed_.is_deleted());
202  }
203  return kErrorCodeOk;
204 }
bool is_valid_record() const __attribute__((always_inline))
0 means no-error.
Definition: error_code.hpp:87
bool is_deleted() const __attribute__((always_inline))
Definition: xct_id.hpp:1040
#define CHECK_ERROR_CODE(x)
This macro calls x and checks its returned error code.
Definition: error_code.hpp:155
#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
xct::XctId observed_
TID as of locate_record() identifying the record.

Here is the call graph for this function:

ErrorCode foedus::storage::masstree::MasstreeCursor::open ( const char *  begin_key = nullptr,
KeyLength  begin_key_length = kKeyLengthExtremum,
const char *  end_key = nullptr,
KeyLength  end_key_length = kKeyLengthExtremum,
bool  forward_cursor = true,
bool  for_writes = false,
bool  begin_inclusive = true,
bool  end_inclusive = false 
)

Definition at line 932 of file masstree_cursor.cpp.

References ASSERT_ND, CHECK_ERROR_CODE, foedus::storage::masstree::copy_input_key(), foedus::storage::masstree::MasstreeStoragePimpl::get_first_root(), foedus::xct::Xct::is_active(), foedus::xct::XctId::is_deleted(), is_valid_record(), kBackwardExclusive, kBackwardInclusive, foedus::kErrorCodeOk, foedus::kErrorCodeXctNoXct, kForwardExclusive, kForwardInclusive, and foedus::storage::masstree::RecordLocation::observed_.

Referenced by open_normalized().

940  {
941  CHECK_ERROR_CODE(allocate_if_not_exist(&routes_));
942  CHECK_ERROR_CODE(allocate_if_not_exist(&search_key_));
943  CHECK_ERROR_CODE(allocate_if_not_exist(&search_key_slices_));
944  CHECK_ERROR_CODE(allocate_if_not_exist(&cur_route_prefix_slices_));
945  CHECK_ERROR_CODE(allocate_if_not_exist(&cur_route_prefix_be_));
946  CHECK_ERROR_CODE(allocate_if_not_exist(&end_key_));
947  CHECK_ERROR_CODE(allocate_if_not_exist(&end_key_slices_));
948 
949  if (!current_xct_->is_active()) {
950  return kErrorCodeXctNoXct;
951  }
952 
953  forward_cursor_ = forward_cursor;
954  reached_end_ = false;
955  for_writes_ = for_writes;
956  end_inclusive_ = end_inclusive;
957  end_key_length_ = end_key_length;
958  route_count_ = 0;
959  if (!is_end_key_supremum()) {
960  copy_input_key(end_key, end_key_length, end_key_, end_key_slices_);
961  }
962 
963  search_key_length_ = begin_key_length;
964  search_type_ = forward_cursor ? (begin_inclusive ? kForwardInclusive : kForwardExclusive)
965  : (begin_inclusive ? kBackwardInclusive : kBackwardExclusive);
966  if (!is_search_key_extremum()) {
967  copy_input_key(begin_key, begin_key_length, search_key_, search_key_slices_);
968  }
969 
970  MasstreeIntermediatePage* root;
971  MasstreeStoragePimpl pimpl(&storage_);
972  CHECK_ERROR_CODE(pimpl.get_first_root(context_, for_writes, &root));
973  CHECK_ERROR_CODE(push_route(root));
974  CHECK_ERROR_CODE(locate_layer(0));
975  ASSERT_ND(route_count_ != 0);
976  ASSERT_ND(cur_route()->page_->is_border());
977  ASSERT_ND(should_skip_cur_route_ || (!should_skip_cur_route_ && is_valid_record()));
978 
979  // In a few cases, open() must move on to next page/key.
980  // 1. locate_xxx doesn't take care of deleted record as it can't proceed to another page.
981  // so, if the initially located record is a deleted record, we need to move on to next key.
982  // 2. unluckily we hit an empty page or the page boundary in initial locate().
983  // Let's go on to next page by proceed_route() and find a next page.
984  // Note, it's a while, not if. It's very unlikely but possible that proceed_route again
985  // results in the same state.
986  while (should_skip_cur_route_
987  || (is_valid_record() && cur_key_location_.observed_.is_deleted())) {
988  DVLOG(0) << "Rare. open() needs to move on to find non-deleted records/pages";
989  should_skip_cur_route_ = false;
990  CHECK_ERROR_CODE(proceed_route());
991  if (route_count_ == 0) {
992  LOG(INFO) << "The empty page was the last page that might have had the record. we are done";
994  return kErrorCodeOk;
995  }
996  }
997  ASSERT_ND(!should_skip_cur_route_);
998  ASSERT_ND(!is_valid_record() || !cur_key_location_.observed_.is_deleted());
999  check_end_key();
1000  if (is_valid_record()) {
1001  assert_route();
1002  }
1003  return kErrorCodeOk;
1004 }
bool is_active() const
Returns whether the object is an active transaction.
Definition: xct.hpp:121
void copy_input_key(const char *input_key, KeyLength length, char *buffer, KeySlice *slice_buffer)
bool is_valid_record() const __attribute__((always_inline))
0 means no-error.
Definition: error_code.hpp:87
bool is_deleted() const __attribute__((always_inline))
Definition: xct_id.hpp:1040
#define CHECK_ERROR_CODE(x)
This macro calls x and checks its returned error code.
Definition: error_code.hpp:155
0x0A04 : "XCTION : This thread is not running any transaction." .
Definition: error_code.hpp:199
#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
xct::XctId observed_
TID as of locate_record() identifying the record.

Here is the call graph for this function:

Here is the caller graph for this function:

ErrorCode foedus::storage::masstree::MasstreeCursor::open_normalized ( KeySlice  begin_key,
KeySlice  end_key,
bool  forward_cursor = true,
bool  for_writes = false,
bool  begin_inclusive = true,
bool  end_inclusive = false 
)
inline

Definition at line 201 of file masstree_cursor.hpp.

References ASSERT_ND, and open().

207  {
208  ASSERT_ND((forward_cursor && end_key >= begin_key) ||
209  (!forward_cursor && end_key <= begin_key));
210  KeySlice begin_key_be = assorted::htobe<KeySlice>(begin_key);
211  KeySlice end_key_be = assorted::htobe<KeySlice>(end_key);
212  return open(
213  reinterpret_cast<const char*>(&begin_key_be),
214  sizeof(KeySlice),
215  reinterpret_cast<const char*>(&end_key_be),
216  sizeof(KeySlice),
217  forward_cursor,
218  for_writes,
219  begin_inclusive,
220  end_inclusive);
221  }
ErrorCode open(const char *begin_key=nullptr, KeyLength begin_key_length=kKeyLengthExtremum, const char *end_key=nullptr, KeyLength end_key_length=kKeyLengthExtremum, bool forward_cursor=true, bool for_writes=false, bool begin_inclusive=true, bool end_inclusive=false)
uint64_t KeySlice
Each key slice is an 8-byte integer.
#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

Here is the call graph for this function:

ErrorCode foedus::storage::masstree::MasstreeCursor::overwrite_record ( const void *  payload,
PayloadLength  payload_offset,
PayloadLength  payload_count 
)

Definition at line 1271 of file masstree_cursor.cpp.

References copy_combined_key(), foedus::storage::masstree::kMaxKeyLength, and foedus::storage::masstree::MasstreeStoragePimpl::overwrite_general().

1274  {
1275  assert_modify();
1276  char key[kMaxKeyLength];
1277  copy_combined_key(key);
1278  return MasstreeStoragePimpl(&storage_).overwrite_general(
1279  context_,
1280  cur_key_location_,
1281  key,
1282  cur_key_length_,
1283  payload,
1284  payload_offset,
1285  payload_count);
1286 }
const KeyLength kMaxKeyLength
Max length of a key.
Definition: masstree_id.hpp:75
void copy_combined_key(char *buffer) const
Copies the entire big-endian key of the current record to the given buffer.

Here is the call graph for this function:

template<typename PAYLOAD >
ErrorCode foedus::storage::masstree::MasstreeCursor::overwrite_record_primitive ( PAYLOAD  payload,
PayloadLength  payload_offset 
)

Definition at line 1289 of file masstree_cursor.cpp.

References copy_combined_key(), foedus::storage::masstree::kMaxKeyLength, and foedus::storage::masstree::MasstreeStoragePimpl::overwrite_general().

1291  {
1292  assert_modify();
1293  char key[kMaxKeyLength];
1294  copy_combined_key(key);
1295  return MasstreeStoragePimpl(&storage_).overwrite_general(
1296  context_,
1297  cur_key_location_,
1298  key,
1299  cur_key_length_,
1300  &payload,
1301  payload_offset,
1302  sizeof(PAYLOAD));
1303 }
const KeyLength kMaxKeyLength
Max length of a key.
Definition: masstree_id.hpp:75
void copy_combined_key(char *buffer) const
Copies the entire big-endian key of the current record to the given buffer.

Here is the call graph for this function:


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