libfoedus-core
FOEDUS Core Library
masstree_cursor.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015, Hewlett-Packard Development Company, LP.
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU General Public License as published by the Free
5  * Software Foundation; either version 2 of the License, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11  * more details. You should have received a copy of the GNU General Public
12  * License along with this program; if not, write to the Free Software
13  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14  *
15  * HP designates this particular file as subject to the "Classpath" exception
16  * as provided by HP in the LICENSE.txt file that accompanied this code.
17  */
18 #ifndef FOEDUS_STORAGE_MASSTREE_MASSTREE_CURSOR_HPP_
19 #define FOEDUS_STORAGE_MASSTREE_MASSTREE_CURSOR_HPP_
20 
21 #include <stdint.h>
22 
23 #include <cstring>
24 #include <string>
25 
26 #include "foedus/assert_nd.hpp"
27 #include "foedus/compiler.hpp"
28 #include "foedus/cxx11.hpp"
29 #include "foedus/engine.hpp"
31 #include "foedus/storage/fwd.hpp"
32 #include "foedus/storage/page.hpp"
38 #include "foedus/thread/fwd.hpp"
39 #include "foedus/xct/xct_id.hpp"
40 
41 namespace foedus {
42 namespace storage {
43 namespace masstree {
76  public:
83  struct Route {
90  kNone = 0,
94  };
125 
127  bool snapshot_;
130 
133 
143 
146 
148  return order_[index_];
149  }
151  return order_[index];
152  }
154  return index_ < key_count_;
155  }
161  bool was_stably_moved() const { return stable_.is_moved(); }
162  void setup_order();
163  };
164  enum SearchType {
169  };
174  // the following two are only when cur key points to next layer. instead, no equals for layer
177  };
178  enum Constants {
182  };
183 
184  MasstreeCursor(MasstreeStorage storage, thread::Thread* context);
185 
186  thread::Thread* get_context() { return context_; }
187  MasstreeStorage& get_storage() { return storage_; }
188  bool is_for_writes() const { return for_writes_; }
189  bool is_forward_cursor() const { return forward_cursor_; }
190 
191  ErrorCode open(
192  const char* begin_key = CXX11_NULLPTR,
193  KeyLength begin_key_length = kKeyLengthExtremum,
194  const char* end_key = CXX11_NULLPTR,
195  KeyLength end_key_length = kKeyLengthExtremum,
196  bool forward_cursor = true,
197  bool for_writes = false,
198  bool begin_inclusive = true,
199  bool end_inclusive = false);
200 
202  KeySlice begin_key,
203  KeySlice end_key,
204  bool forward_cursor = true,
205  bool for_writes = false,
206  bool begin_inclusive = true,
207  bool end_inclusive = false) {
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  }
222 
224  return route_count_ > 0 && !reached_end_ && cur_route()->is_valid_record();
225  }
229  return cur_key_length_;
230  }
236  return cur_route_prefix_slices_;
237  }
240  return cur_route_prefix_be_;
241  }
245  return cur_key_in_layer_slice_;
246  }
248  const char* get_key_suffix() const ALWAYS_INLINE {
250  return cur_key_suffix_;
251  }
255  ASSERT_ND(cur_key_length_ <= sizeof(KeySlice));
256  return cur_key_in_layer_slice_;
257  };
276  void copy_combined_key(char* buffer) const;
278  void copy_combined_key_part(KeyLength offset, KeyLength len, char* buffer) const;
280  std::string get_combined_key() const ALWAYS_INLINE {
281  char buf[kMaxKeyLength];
282  copy_combined_key(buf);
283  return std::string(buf, cur_key_length_);
284  }
285 
286  const char* get_payload() const ALWAYS_INLINE {
288  return cur_payload_;
289  }
292  return cur_payload_length_;
293  }
294 
305  ErrorCode next();
306 
307 
309 
311  const void* payload,
312  PayloadLength payload_offset,
313  PayloadLength payload_count);
314  template <typename PAYLOAD>
316  PAYLOAD payload,
317  PayloadLength payload_offset);
318 
319  template <typename PAYLOAD>
320  ErrorCode increment_record(PAYLOAD* value, PayloadLength payload_offset);
321 
322  private:
323  Engine* const engine_;
324  MasstreeStorage storage_;
325  thread::Thread* const context_;
326  xct::Xct* const current_xct_;
327 
328  bool for_writes_;
329  bool forward_cursor_;
330  bool end_inclusive_;
331  bool reached_end_;
332 
334  KeyLength end_key_length_;
336  KeyLength cur_key_length_;
337  PayloadLength cur_payload_length_;
339  KeyLength search_key_length_;
340  SearchType search_type_;
341  bool search_key_in_layer_extremum_;
342 
344  uint16_t route_count_;
345 
358  bool should_skip_cur_route_;
359 
360  bool cur_key_next_layer_;
361  KeyLength cur_key_in_layer_remainder_;
362  KeySlice cur_key_in_layer_slice_;
367  RecordLocation cur_key_location_;
368  // xct::XctId cur_key_observed_owner_id_;
369  xct::RwLockableXctId* cur_key_owner_id_address;
370 
372  char* end_key_;
374  KeySlice* end_key_slices_;
375 
381  KeySlice* cur_route_prefix_slices_;
383  char* cur_route_prefix_be_;
389  const char* cur_key_suffix_;
390 
392  const char* cur_payload_;
393 
395  char* search_key_;
397  KeySlice* search_key_slices_;
398 
400  PageVersionStatus cur_page_stable_;
401 
403  Route* routes_;
404 
409  ErrorCode push_route(MasstreePage* page);
414  ErrorCode fetch_cur_record_logical(MasstreeBorderPage* page, SlotIndex record);
415  void check_end_key();
416  bool is_cur_key_next_layer() const { return cur_key_location_.observed_.is_next_layer(); }
417  KeyCompareResult compare_cur_key_aginst_search_key(KeySlice slice, uint8_t layer) const;
418  KeyCompareResult compare_cur_key_aginst_end_key() const;
419  KeyCompareResult compare_cur_key(
420  KeySlice slice,
421  uint8_t layer,
422  const char* full_key,
423  KeyLength full_length) const;
424 
425  SlotIndex get_cur_index() const ALWAYS_INLINE {
427  return cur_route()->get_cur_original_index();
428  }
429  MasstreePage* get_cur_page() const ALWAYS_INLINE {
431  return cur_route()->page_;
432  }
433 
434  Route* cur_route() ALWAYS_INLINE {
435  ASSERT_ND(route_count_ > 0);
436  return routes_ + route_count_ - 1;
437  }
438  const Route* cur_route() const ALWAYS_INLINE {
439  ASSERT_ND(route_count_ > 0);
440  return routes_ + route_count_ - 1;
441  }
442 
443  template <typename T>
444  ErrorCode allocate_if_not_exist(T** pointer);
445 
446  bool is_search_key_extremum() const ALWAYS_INLINE {
447  return search_key_length_ == kKeyLengthExtremum;
448  }
449  bool is_end_key_supremum() const ALWAYS_INLINE {
450  return end_key_length_ == kKeyLengthExtremum;
451  }
452 
453  ErrorCode follow_foster_border(KeySlice slice);
454  void extract_separators(KeySlice* separator_low, KeySlice* separator_high) const ALWAYS_INLINE;
455 
466 
472  ErrorCode locate_layer(uint8_t layer);
478  ErrorCode locate_border(KeySlice slice);
482  ErrorCode locate_next_layer();
488  ErrorCode locate_descend(KeySlice slice);
489 
490  // proceed_xxx is for next
491  ErrorCode proceed_route();
492  ErrorCode proceed_route_border();
493  ErrorCode proceed_route_intermediate();
494  ErrorCode proceed_pop();
495  ErrorCode proceed_next_layer();
496  ErrorCode proceed_deeper();
497  ErrorCode proceed_deeper_border();
498  ErrorCode proceed_deeper_intermediate();
499  void proceed_route_intermediate_rebase_separator();
500 
501  void set_should_skip_cur_route();
502 
503  MasstreePage* resolve_volatile(VolatilePagePointer ptr) const;
504 
505  void assert_modify() const ALWAYS_INLINE {
506 #ifndef NDEBUG
507  ASSERT_ND(!should_skip_cur_route_);
508  ASSERT_ND(for_writes_);
510  ASSERT_ND(!cur_route()->snapshot_);
511  ASSERT_ND(reinterpret_cast<Page*>(get_cur_page())->get_header().get_page_type()
513 #endif // NDEBUG
514  }
515  void assert_route() const ALWAYS_INLINE {
516 #ifndef NDEBUG
517  assert_route_impl();
518 #endif // NDEBUG
519  }
520  void assert_route_impl() const;
521 };
522 
523 } // namespace masstree
524 } // namespace storage
525 } // namespace foedus
526 #endif // FOEDUS_STORAGE_MASSTREE_MASSTREE_CURSOR_HPP_
const char * get_payload() const __attribute__((always_inline))
MovedPageSearchStatus moved_page_search_status_
only when stable_ indicates that this page is a moved page
This means either was_stably_moved() is false or it's intermediate page, in which case we don't neeed...
uint16_t PayloadLength
Represents a byte-length of a payload in this package.
Definition: masstree_id.hpp:92
Definitions of IDs in this package and a few related constant values.
ErrorCode overwrite_record_primitive(PAYLOAD payload, PayloadLength payload_offset)
uint16_t SlotIndex
Index of a record in a (border) page.
#define CXX11_NULLPTR
Used in public headers in place of "nullptr" of C++11.
Definition: cxx11.hpp:132
KeySlice get_normalized_key() const __attribute__((always_inline))
This method assumes the key length is at most 8 bytes.
const KeyLength kMaxKeyLength
Max length of a key.
Definition: masstree_id.hpp:75
std::string get_combined_key() const __attribute__((always_inline))
For even handier use, it returns std::string.
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
Represents one thread running on one NUMA core.
Definition: thread.hpp:48
bool is_moved() const __attribute__((always_inline))
Definition: page.hpp:71
ErrorCode next()
Moves the cursor to next record.
Represents a user transaction.
Definition: xct.hpp:58
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)
Represents one border page in Masstree Storage.
void copy_combined_key(char *buffer) const
Copies the entire big-endian key of the current record to the given buffer.
uint64_t KeySlice
Each key slice is an 8-byte integer.
Definitions of IDs in this package and a few related constant values.
uint16_t KeyLength
Represents a byte-length of a key in this package.
Definition: masstree_id.hpp:69
A few macros and helper methods related to byte endian-ness.
Common base of MasstreeIntermediatePage and MasstreeBorderPage.
const char * get_cur_route_prefix_be() const __attribute__((always_inline))
Big-endian version.
KeySlice latest_separator_
Upto which separator we are done.
Represents one page in the current search path from layer0-root.
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.
The MCS reader-writer lock variant of LockableXctId.
Definition: xct_id.hpp:1132
SlotIndex get_cur_original_index() const __attribute__((always_inline))
uint8_t Layer
Represents the depth of a B-trie layer.
Definition: masstree_id.hpp:42
bool is_valid_record() const __attribute__((always_inline))
Forward declarations of classes in storage package.
Definitions of IDs in this package and a few related constant values.
PayloadLength get_payload_length() const __attribute__((always_inline))
SlotIndex get_original_index(SlotIndex index) const __attribute__((always_inline))
#define CXX11_FINAL
Used in public headers in place of "final" of C++11.
Definition: cxx11.hpp:131
Database engine object that holds all resources and provides APIs.
Definition: engine.hpp:109
const SlotIndex kBorderPageMaxSlots
Maximum number of slots in one MasstreeBorderPage.
bool is_next_layer() const __attribute__((always_inline))
Definition: xct_id.hpp:1042
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)
MasstreeCursor(MasstreeStorage storage, thread::Thread *context)
PageVersionStatus stable_
version as of calculating order_.
KeySlice get_key_in_layer_slice() const __attribute__((always_inline))
Returns only the slice of the key in the layer of the current page.
KeyLength get_key_length() const __attribute__((always_inline))
Returns the length of the whole key we are currently pointing to.
SlotIndex key_count_
same as stable_.get_key_count()
Layer layer_
Shorthand for page_->get_layer()
SlotIndex order_[kBorderPageMaxSlots]
only for border.
const KeySlice * get_cur_route_prefix_slices() const __attribute__((always_inline))
Returns the prefix slices upto the current page.
Represents a cursor object for Masstree storage.
Forward declarations of classes in masstree storage package.
#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
ErrorCode overwrite_record(const void *payload, PayloadLength payload_offset, PayloadLength payload_count)
Forward declarations of classes in thread package.
#define ALWAYS_INLINE
A function suffix to hint that the function should always be inlined.
Definition: compiler.hpp:106
xct::XctId observed_
TID as of locate_record() identifying the record.
return value of MasstreeStoragePimpl::locate_record()/reserve_record().
bool snapshot_
whether page_ is a snapshot page
const uint16_t kPageSize
A constant defining the page size (in bytes) of both snapshot pages and volatile pages.
Definition: storage_id.hpp:45
ErrorCode
Enum of error codes defined in error_code.xmacro.
Definition: error_code.hpp:85
ErrorCode increment_record(PAYLOAD *value, PayloadLength payload_offset)
bool was_stably_moved() const
In almost all places of the cursor code, we check is_moved() only on the stable version so that the c...
bool is_valid_record() const __attribute__((always_inline))
const char * get_key_suffix() const __attribute__((always_inline))
Returns the suffix part of the key in the page.