libfoedus-core
FOEDUS Core Library
foedus::storage::hash Namespace Reference

Hashtable Storage, a concurrent hashtable. More...

Detailed Description

Hashtable Storage, a concurrent hashtable.

What we have here is a quite simple hash storage. Allthemore simple, more robust and scalable.

Hash Interemediate page and Data page

The hash storage has two types of pages: HashIntermediatePage and HashDataPage. HashIntermediatePage, starting from the root page, points down to other intermediate pages, and the level-0 intermediate pages point to HashDataPage. HashDataPage has a next-pointer. One entry (pointer) in a level-0 intermediate page corresponds to a hash bin. Usually one hash bin corresponds to a very small number of data pages, zero, one or rarely two.

foedus::storage::hash::HashIntermediatePage foedus::storage::hash::HashDataPage

Singly-linked data pages, hopefully rarely used

When a hash bin receives many records or very long key or values, a data page contains a link to next page that forms a singly-linked list of pages. Although this is a dual page pointer, we use only one of them. Snapshot hash pages of course point to only snapshot hash pages. Volatile hash pages, to simplify, also point to only volatile hash pages.

In other words, when we make a volatile version of any page in a hash bin, we instantiate volatile pages for all pages in the hash bin. This might sound costly, but there should be only 1 or only occasionaly a few pages in the bin, assuming 1) bin-bits that is large enough, and 2) good hash function.

Locking Protocol

Intermediate pages are completely lock-free. Data pages do have per-page and per-tuple locks. Hopefully most locks are per-tuple, meaning just taking the TID of the tuple as read-set or write-set. However, there are a few cases the thread must take an exclusive lock in page-header.

  • Inserting a new tuple. A system-transaction takes a page-lock, places a logically-deleted tuple with the hash/key, modifies the page header, releases the lock.
  • Installing a next-page pointer. A system-transaction creates an empty next-page, takes a page-lock, installs the pointer to the new page, modifies the page header, releases the lock.
  • Migrating a tuple for expansion. Also a system transaction. Detailed in next section.
  • Miss-search. A user-transaction adds the page header of the tail page to PageVersionSet and verifies it at pre-commit.

All of the above are quite similar to masstree package's insertion/splits/miss-search. Like masstree package, the full-hash/key of a physical tuple is immutable once installed. We only use logical deletion flags and "moved" bits to allow record expansion. Also like masstree, other operations proceed without locks or in many cases even atomic operations, just a few memory barriers. For example, deletion just puts a logical deletion flag to the record without page-lock. Reading is completely atomics-free as far as you find the exact record (miss-search is a bit more complicated as above).

Flags in TID of Hash storages

To implement the above protocol, the moved bit in TID has a bit different meaning from masstree package. It means that the corresponding record for the full-hash/key is somewhere later in the list. When we need to expand a record space that is not at the end, we insert a new physical tuple for the record with large space, then put the "moved" bit in the original physical record. If threads see the flag while processing, it skips such a record. If pre-commit sees the flag because of concurrent migration, it tracks the moved record just like Master-Tree protocol. The idea is almost the same, but here the tracking is much simpler. Just follow the linked list.

History note, or a tombstone
We initially considered a bit more fancy hash storages (namely Cuckoo Hashing), but we didn't see enough benefits to justify its limitations (eg, how to structure snapshot pages if a tuple might be placed in two bins!). The only case it is useful is when the hash bins are really close to full, but we'll just have larger hash storages to avoid such a case. On huge NVRAM (whose density will also quickly grow), 100% fill-factor doesn't buy us anything significant over 50%. Hence discarded that plan. A sad war story, but ain't gonna win all wars. Keep it simple stupid, men.

Classes

struct  BloomFilterFingerprint
 A fingerprint for bloom filter in each HashDataPage. More...
 
struct  ComposedBin
 Represents an output of composer on one bin. More...
 
struct  ComposedBinsBuffer
 Abstracts how we batch-read several HashComposedBinsPage emit from individual composers. More...
 
struct  ComposedBinsMergedStream
 Packages all ComposedBinsBuffer to easily extract bins of current interest. More...
 
struct  DataPageBloomFilter
 To quickly check whether a HashDataPage might contain a specific hash value, we maintain a non-counting bloom filter in each page. More...
 
struct  HashBinRange
 Represents a range of hash bins in a hash storage, such as what an intermediate page is responsible for. More...
 
struct  HashCombo
 A set of information that are used in many places, extracted from the given key. More...
 
struct  HashCommonLogType
 A base class for HashInsertLogType/HashDeleteLogType/HashOverwriteLogType. More...
 
class  HashComposeContext
 HashComposer's compose() implementation separated from the class itself. More...
 
struct  HashComposedBinsPage
 A page to pack many ComposedBin as an output of composer. More...
 
class  HashComposer
 Composer for a hash storage. More...
 
struct  HashCreateLogType
 Log type of CREATE HASH STORAGE operation. More...
 
class  HashDataPage
 Represents an individual data page in Hashtable Storage. More...
 
struct  HashDeleteLogType
 Log type of hash-storage's delete operation. More...
 
struct  HashInsertLogType
 Log type of hash-storage's insert operation. More...
 
class  HashIntermediatePage
 Represents an intermediate page in Hashtable Storage. More...
 
struct  HashMetadata
 Metadata of an hash storage. More...
 
struct  HashMetadataSerializer
 
struct  HashOverwriteLogType
 Log type of hash-storage's overwrite operation. More...
 
class  HashPartitioner
 Partitioner for a hash storage. More...
 
struct  HashPartitionerData
 
class  HashStorage
 Represents a key-value store based on a dense and regular hash. More...
 
struct  HashStorageControlBlock
 Shared data of this storage type. More...
 
class  HashStoragePimpl
 Pimpl object of HashStorage. More...
 
class  HashTmpBin
 An in-memory single-threaded data structure to compose tuples in a hash bin. More...
 
struct  HashUpdateLogType
 Log type of hash-storage's update operation. More...
 
union  IntermediateRoute
 Compactly represents the route of intermediate pages to reach the given hash bin. More...
 
struct  RecordLocation
 return value of locate_record(). More...
 
struct  ReserveRecords
 A system transaction to reserve a physical record(s) in a hash data page. More...
 
struct  SortEntry
 Used in sort_batch(). More...
 
struct  TmpSnashotPage
 

Typedefs

typedef HashIntermediatePage HashRootInfoPage
 Output of one compose() call, which are then combined in construct_root(). More...
 
typedef uint64_t HashValue
 Represents a full 64-bit hash value calculated from a key. More...
 
typedef uint64_t HashBin
 Represents a bin of a hash value. More...
 
typedef uint16_t DataPageSlotIndex
 
typedef uint16_t KeyLength
 Represents a byte-length of a key in this package. More...
 
typedef uint16_t PayloadLength
 Represents a byte-length of a payload in this package. More...
 

Functions

HashValue hashinate (const void *key, uint16_t key_length)
 Calculates hash value for general input. More...
 
template<typename T >
HashValue hashinate (T key)
 Calculates hash value for a primitive type. More...
 
uint64_t fanout_power (uint8_t exponent)
 
uint8_t bins_to_level (uint64_t bins)
 
void hash_intermediate_volatile_page_init (const VolatilePageInitArguments &args)
 volatile page initialize callback for HashIntermediatePage. More...
 
void hash_data_volatile_page_init (const VolatilePageInitArguments &args)
 volatile page initialize callback for HashDataPage. More...
 
std::ostream & operator<< (std::ostream &o, const HashCombo &v)
 
HashDataPageresolve_data_impl (const memory::GlobalVolatilePageResolver &resolver, VolatilePagePointer pointer)
 
HashIntermediatePageresolve_intermediate_impl (const memory::GlobalVolatilePageResolver &resolver, VolatilePagePointer pointer)
 
std::ostream & operator<< (std::ostream &o, const BloomFilterFingerprint &v)
 
std::ostream & operator<< (std::ostream &o, const IntermediateRoute &v)
 
std::ostream & operator<< (std::ostream &o, const DataPageBloomFilter &v)
 
std::ostream & operator<< (std::ostream &o, const HashBinRange &v)
 
std::ostream & operator<< (std::ostream &o, const HashCreateLogType &v)
 
std::ostream & operator<< (std::ostream &o, const HashInsertLogType &v)
 
std::ostream & operator<< (std::ostream &o, const HashDeleteLogType &v)
 
std::ostream & operator<< (std::ostream &o, const HashUpdateLogType &v)
 
std::ostream & operator<< (std::ostream &o, const HashOverwriteLogType &v)
 
std::ostream & operator<< (std::ostream &o, const HashMetadata &v)
 
std::ostream & operator<< (std::ostream &o, const HashIntermediatePage &v)
 
std::ostream & operator<< (std::ostream &o, const HashDataPage &v)
 
void release_parallel (Engine *engine, VolatilePagePointer pointer)
 
void design_partition_thread (HashPartitioner *partitioner, uint16_t task)
 
void prepare_sort_entries (uint8_t bin_shifts, const Partitioner::SortBatchArguments &args, SortEntry *entries)
 subroutine of sort_batch More...
 
uint32_t compact_logs (uint8_t, const Partitioner::SortBatchArguments &args, SortEntry *entries)
 subroutine of sort_batch More...
 
std::ostream & operator<< (std::ostream &o, const HashPartitioner &v)
 
std::ostream & operator<< (std::ostream &o, const HashStorage &v)
 
uint16_t adjust_payload_hint (uint16_t payload_count, uint16_t physical_payload_hint)
 
std::ostream & operator<< (std::ostream &o, const HashTmpBin &v)
 

Variables

const uint16_t kHashComposedBinsPageMaxBins = (kPageSize - 80) / sizeof(ComposedBin)
 
const uint64_t kXxhashKeySeed = 0x3f119e0435262a17ULL
 Default seed value used for xxhash's xxh32/64 to hashinate keys. More...
 
const uint16_t kHashDataPageBloomFilterBytes = 64
 Byte size of bloom filter in each HashDataPage. More...
 
const uint16_t kHashDataPageBloomFilterBits = kHashDataPageBloomFilterBytes * 8
 Bit size of bloom filter in each HashDataPage. More...
 
const uint8_t kHashDataPageBloomFilterIndexSize = 9U
 How many bits we need in order to represent an index in bloom filter in each HashDataPage. More...
 
const HashValue kHashDataPageBloomFilterIndexMask = (1U << kHashDataPageBloomFilterIndexSize) - 1U
 
const uint8_t kHashDataPageBloomFilterHashes = 3
 Number of hash functions (k) of bloom filter in each HashDataPage. More...
 
const uint16_t kHashIntermediatePageHeaderSize = 64
 Byte size of header in an intermediate page of hash storage. More...
 
const uint8_t kHashIntermediatePageFanout
 Number of pointers in an intermediate page of hash storage. More...
 
const uint64_t kFanout64 = kHashIntermediatePageFanout
 just to write the following concisely More...
 
const uint64_t kHashMaxBins []
 kHashTotalBins[n] gives the maximum number of hash bins n-level hash can hold. More...
 
const uint8_t kHashMaxLevels = 8
 Max level of intermediate pages. More...
 
const uint16_t kHashDataPageHeaderSize = 128
 Byte size of header in data page of hash storage. More...
 
const uint16_t kHashDataPageDataSize = kPageSize - kHashDataPageHeaderSize
 Body data byte size in data page of hash storage. More...
 
const uint8_t kHashMinBinBits = 7U
 Minimum number allowed for bin-bits. More...
 
const uint8_t kHashMaxBinBits = 48U
 Maximum number allowed for bin-bits. More...
 
const HashBin kInvalidHashBin = 1ULL << kHashMaxBinBits
 This value or larger never appears as a valid HashBin. More...
 
const DataPageSlotIndex kSlotNotFound = 0xFFFFU
 

Typedef Documentation

Definition at line 196 of file hash_id.hpp.

Function Documentation

uint16_t foedus::storage::hash::adjust_payload_hint ( uint16_t  payload_count,
uint16_t  physical_payload_hint 
)

Definition at line 250 of file hash_storage_pimpl.cpp.

References foedus::assorted::align8(), and ASSERT_ND.

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

250  {
251  ASSERT_ND(physical_payload_hint >= payload_count); // if not, most likely misuse.
252  if (physical_payload_hint < payload_count) {
253  physical_payload_hint = payload_count;
254  }
255  physical_payload_hint = assorted::align8(physical_payload_hint);
256  return physical_payload_hint;
257 }
T align8(T value)
8-alignment.
#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:

uint32_t foedus::storage::hash::compact_logs ( uint8_t  ,
const Partitioner::SortBatchArguments args,
SortEntry entries 
)

subroutine of sort_batch

Definition at line 261 of file hash_partitioner_impl.cpp.

References foedus::storage::hash::SortEntry::get_position(), foedus::storage::Partitioner::SortBatchArguments::logs_count_, and foedus::storage::Partitioner::SortBatchArguments::output_buffer_.

Referenced by foedus::storage::hash::HashPartitioner::sort_batch().

264  {
265  // TASK(Hideaki) mapper side compaction.
266  // Unlike array, we have to consider all combinations of insert/delete/overwrite.
267  // Also needs to exactly compare keys. We probably need to store hashes in log to make it worth.
268  for (uint32_t i = 0; i < args.logs_count_; ++i) {
269  args.output_buffer_[i] = entries[i].get_position();
270  }
271  return args.logs_count_;
272 /*
273  // CPU profile of partition_hash_perf: ??%.
274  uint32_t result_count = 1;
275  args.output_buffer_[0] = entries[0].get_position();
276  HashBin prev_bin = entries[0].get_bin();
277  for (uint32_t i = 1; i < args.logs_count_; ++i) {
278  // compact the logs if the same offset appears in a row, and covers the same data region.
279  // because we sorted it by offset and then ordinal, later logs can overwrite the earlier one.
280  HashBin cur_bin = entries[i].get_bin();
281  if (UNLIKELY(cur_bin == prev_bin)) {
282  const log::RecordLogType* prev_p = args.log_buffer_.resolve(entries[i - 1].get_position());
283  log::RecordLogType* next_p = args.log_buffer_.resolve(entries[i].get_position());
284  if (prev_p->header_.log_type_code_ != next_p->header_.log_type_code_) {
285  // increment log can be superseded by overwrite log,
286  // overwrite log can be merged with increment log.
287  // however, these usecases are probably much less frequent than the following.
288  // so, we don't compact this case so far.
289  } else if (prev_p->header_.get_type() == log::kLogCodeHashOverwrite) {
290  // two overwrite logs might be compacted
291  const HashOverwriteLogType* prev = reinterpret_cast<const HashOverwriteLogType*>(prev_p);
292  const HashOverwriteLogType* next = reinterpret_cast<const HashOverwriteLogType*>(next_p);
293  // is the data region same or superseded?
294  uint16_t prev_begin = prev->payload_offset_;
295  uint16_t prev_end = prev_begin + prev->payload_count_;
296  uint16_t next_begin = next->payload_offset_;
297  uint16_t next_end = next_begin + next->payload_count_;
298  if (next_begin <= prev_begin && next_end >= prev_end) {
299  --result_count;
300  }
301 
302  // the logic checks data range against only the previous entry.
303  // we might have a situation where 3 or more log entries have the same hash offset
304  // and the data regions are like following
305  // Log 1: [4, 8) bytes, Log 2: [8, 12) bytes, Log 3: [4, 8) bytes
306  // If we check further, Log 3 can eliminate Log 1. However, the check is expensive..
307  } else {
308  // two increment logs of same type/offset can be merged into one.
309  ASSERT_ND(prev_p->header_.get_type() == log::kLogCodeHashIncrement);
310  const HashIncrementLogType* prev = reinterpret_cast<const HashIncrementLogType*>(prev_p);
311  HashIncrementLogType* next = reinterpret_cast<HashIncrementLogType*>(next_p);
312  if (prev->value_type_ == next->value_type_
313  && prev->payload_offset_ == next->payload_offset_) {
314  // add up the prev's addendum to next, then delete prev.
315  next->merge(*prev);
316  --result_count;
317  }
318  }
319  } else {
320  prev_bin = cur_bin;
321  }
322  args.output_buffer_[result_count] = entries[i].get_position();
323  ++result_count;
324  }
325  return result_count;
326  */
327 }

Here is the call graph for this function:

Here is the caller graph for this function:

void foedus::storage::hash::design_partition_thread ( HashPartitioner partitioner,
uint16_t  task 
)

Definition at line 64 of file hash_partitioner_impl.cpp.

References foedus::storage::hash::HashPartitioner::design_partition_task().

Referenced by foedus::storage::hash::HashPartitioner::design_partition().

64  {
65  partitioner->design_partition_task(task);
66 }

Here is the call graph for this function:

Here is the caller graph for this function:

std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashBinRange v 
)

Defined in hash_id.cpp

Definition at line 28 of file hash_id.cpp.

References foedus::storage::hash::HashBinRange::begin_, and foedus::storage::hash::HashBinRange::end_.

28  {
29  o << "<HashBinRange from=\""
30  << assorted::Hex(v.begin_)
31  << "\" to=\"" << assorted::Hex(v.end_) << "\" />";
32  return o;
33 }
std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashIntermediatePage v 
)

Definition at line 31 of file hash_page_debug.cpp.

References foedus::storage::hash::HashBinRange::begin_, foedus::storage::hash::HashIntermediatePage::get_bin_range(), foedus::storage::hash::HashIntermediatePage::get_level(), foedus::storage::hash::HashIntermediatePage::get_pointer(), foedus::storage::hash::HashIntermediatePage::header(), foedus::storage::DualPagePointer::is_both_null(), kHashIntermediatePageFanout, and kHashMaxBins.

31  {
32  o << "<HashIntermediatePage>";
33  o << std::endl << " <vaddr>" << assorted::Hex(reinterpret_cast<uintptr_t>(&v), 16) << "</vaddr>";
34  o << std::endl << " " << v.header();
35  o << std::endl << " <level>" << static_cast<int>(v.get_level()) << "</level>";
36  o << std::endl << " " << v.get_bin_range();
37  HashBin total_begin = v.get_bin_range().begin_;
38  HashBin interval = kHashMaxBins[v.get_level()];
39  for (uint16_t i = 0; i < kHashIntermediatePageFanout; ++i) {
40  DualPagePointer pointer = v.get_pointer(i);
41  if (pointer.is_both_null()) {
42  continue;
43  }
44  o << std::endl << " <Pointer index=\"" << static_cast<int>(i)
45  << "\" bin_begin=\"" << (total_begin + i * interval)
46  << "\">" << pointer << "</Pointer>";
47  }
48  o << "</HashIntermediatePage>";
49  return o;
50 }
uint64_t HashBin
Represents a bin of a hash value.
Definition: hash_id.hpp:142
const uint8_t kHashIntermediatePageFanout
Number of pointers in an intermediate page of hash storage.
Definition: hash_id.hpp:49
const uint64_t kHashMaxBins[]
kHashTotalBins[n] gives the maximum number of hash bins n-level hash can hold.
Definition: hash_id.hpp:74

Here is the call graph for this function:

std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashMetadata v 
)

Definition at line 34 of file hash_metadata.cpp.

34  {
35  o << HashMetadataSerializer(const_cast<HashMetadata*>(&v));
36  return o;
37 }
std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashCombo v 
)

Definition at line 37 of file hash_combo.cpp.

References foedus::storage::hash::HashCombo::bin_, foedus::storage::hash::HashCombo::fingerprint_, foedus::storage::hash::HashCombo::hash_, and foedus::storage::hash::HashCombo::route_.

37  {
38  o << "<HashCombo>"
39  << "<hash>" << assorted::Hex(v.hash_, 16) << "</hash>"
40  << "<bin>" << v.bin_ << "</bin>"
41  << v.fingerprint_
42  << v.route_
43  << "</HashCombo>";
44  return o;
45 }
std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashCreateLogType v 
)

Definition at line 47 of file hash_log_types.cpp.

References foedus::storage::hash::HashCreateLogType::metadata_.

47  {
48  o << "<HashCreateLog>" << v.metadata_ << "</HashCreateLog>";
49  return o;
50 }
std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashDataPage v 
)

Definition at line 52 of file hash_page_debug.cpp.

References foedus::storage::hash::DataPageBloomFilter::extract_fingerprint(), foedus::storage::hash::HashDataPage::Slot::get_aligned_key_length(), foedus::storage::hash::HashDataPage::get_bin(), foedus::storage::hash::HashDataPage::get_record_count(), foedus::storage::hash::HashDataPage::get_slot_address(), foedus::storage::hash::HashDataPage::Slot::hash_, foedus::storage::hash::HashDataPage::header(), foedus::storage::hash::HashDataPage::Slot::key_length_, foedus::storage::hash::HashDataPage::next_page(), foedus::storage::hash::HashDataPage::Slot::offset_, foedus::storage::hash::HashDataPage::Slot::payload_length_, foedus::storage::hash::HashDataPage::Slot::physical_record_length_, foedus::storage::hash::HashDataPage::record_from_offset(), and foedus::storage::hash::HashDataPage::Slot::tid_.

52  {
53  o << "<HashDataPage>";
54  o << std::endl << " <vaddr>" << assorted::Hex(reinterpret_cast<uintptr_t>(&v), 16) << "</vaddr>";
55  o << std::endl << v.header();
56  o << std::endl << " <bin>" << assorted::Hex(v.get_bin()) << "</bin>";
57  uint16_t records = v.get_record_count();
58  o << std::endl << " <record_count>" << records << "</record_count>";
59  o << std::endl << " <next_page>" << v.next_page() << "</next_page>";
60  o << std::endl << " <records>";
61  for (DataPageSlotIndex i = 0; i < records; ++i) {
62  const HashDataPage::Slot* slot = v.get_slot_address(i);
63  o << std::endl << " <record index=\"" << i
64  << "\" hash=\"" << assorted::Hex(slot->hash_, 16)
65  << "\" physical_record_len=\"" << slot->physical_record_length_
66  << "\" key_length_=\"" << slot->key_length_
67  << "\" offset=\"" << slot->offset_
68  << "\" payload_len=\"" << slot->payload_length_
69  << "\">";
70  const char* data = v.record_from_offset(slot->offset_);
71  std::string key(data, slot->key_length_);
72  o << "<key>" << assorted::HexString(key) << "</key>";
73  if (slot->payload_length_ > 0) {
74  std::string payload(data + slot->get_aligned_key_length(), slot->payload_length_);
75  o << "<payload>" << assorted::HexString(payload) << "</payload>";
76  }
77  BloomFilterFingerprint fingerprint = DataPageBloomFilter::extract_fingerprint(slot->hash_);
78  o << fingerprint;
79  o << slot->tid_;
80  o << "</record>";
81  }
82  o << std::endl << " </records>";
83  o << std::endl << " <BloomFilter>" << v.bloom_filter_ << "</BloomFilter>";
84  o << "</HashDataPage>";
85  return o;
86 }
uint16_t DataPageSlotIndex
Definition: hash_id.hpp:196

Here is the call graph for this function:

std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashInsertLogType v 
)

Definition at line 52 of file hash_log_types.cpp.

References foedus::storage::hash::HashCommonLogType::bin_bits_, foedus::storage::hash::HashCommonLogType::get_key(), foedus::storage::hash::HashCommonLogType::get_payload(), foedus::storage::hash::HashCommonLogType::hash_, foedus::storage::hash::HashCommonLogType::key_length_, and foedus::storage::hash::HashCommonLogType::payload_count_.

52  {
53  o << "<HashInsertLogType>"
54  << "<key_length_>" << v.key_length_ << "</key_length_>"
55  << "<key_>" << assorted::Top(v.get_key(), v.key_length_) << "</key_>"
56  << "<bin_bits_>" << static_cast<int>(v.bin_bits_) << "</bin_bits_>"
57  << "<hash_>" << assorted::Hex(v.hash_, 16) << "</hash_>"
58  << "<payload_count_>" << v.payload_count_ << "</payload_count_>"
59  << "<payload_>" << assorted::Top(v.get_payload(), v.payload_count_) << "</payload_>"
60  << "</HashInsertLogType>";
61  return o;
62 }

Here is the call graph for this function:

std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const BloomFilterFingerprint v 
)

Definition at line 55 of file hash_hashinate.cpp.

References foedus::storage::hash::BloomFilterFingerprint::indexes_, and kHashDataPageBloomFilterHashes.

55  {
56  o << "<Fingerprint indexes=\"";
57  for (uint8_t i = 0; i < kHashDataPageBloomFilterHashes; ++i) {
58  o << v.indexes_[i] << ",";
59  }
60  o << "\" />";
61  return o;
62 }
const uint8_t kHashDataPageBloomFilterHashes
Number of hash functions (k) of bloom filter in each HashDataPage.
std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashDeleteLogType v 
)

Definition at line 64 of file hash_log_types.cpp.

References foedus::storage::hash::HashCommonLogType::bin_bits_, foedus::storage::hash::HashCommonLogType::get_key(), foedus::storage::hash::HashCommonLogType::hash_, and foedus::storage::hash::HashCommonLogType::key_length_.

64  {
65  o << "<HashDeleteLogType>"
66  << "<key_length_>" << v.key_length_ << "</key_length_>"
67  << "<key_>" << assorted::Top(v.get_key(), v.key_length_) << "</key_>"
68  << "<bin_bits_>" << static_cast<int>(v.bin_bits_) << "</bin_bits_>"
69  << "<hash_>" << assorted::Hex(v.hash_, 16) << "</hash_>"
70  << "</HashDeleteLogType>";
71  return o;
72 }

Here is the call graph for this function:

std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const IntermediateRoute v 
)

Definition at line 64 of file hash_hashinate.cpp.

References foedus::storage::hash::IntermediateRoute::route.

64  {
65  o << "<Route>";
66  for (uint8_t i = 0; i < 8U; ++i) {
67  o << assorted::Hex(v.route[i], 2) << " ";
68  }
69  o << "</Route>";
70  return o;
71 }
std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const DataPageBloomFilter v 
)

Definition at line 73 of file hash_hashinate.cpp.

References kHashDataPageBloomFilterBytes, and foedus::storage::hash::DataPageBloomFilter::values_.

73  {
74  o << "<DataPageBloomFilter>" << std::endl;
75  // one line for 8 bytes
76  for (uint16_t i = 0; i * 8U < kHashDataPageBloomFilterBytes; ++i) {
77  o << " <Bytes row=\"" << i << "\">";
78  for (uint16_t j = i * 8U; j < (i + 1U) * 8U && j < kHashDataPageBloomFilterBytes; ++j) {
79  o << assorted::Hex(v.values_[j], 2) << " ";
80  }
81  o << "</Bytes>" << std::endl;
82  }
83  o << "</DataPageBloomFilter>";
84  return o;
85 }
const uint16_t kHashDataPageBloomFilterBytes
Byte size of bloom filter in each HashDataPage.
std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashUpdateLogType v 
)

Definition at line 74 of file hash_log_types.cpp.

References foedus::storage::hash::HashCommonLogType::bin_bits_, foedus::storage::hash::HashCommonLogType::get_key(), foedus::storage::hash::HashCommonLogType::get_payload(), foedus::storage::hash::HashCommonLogType::hash_, foedus::storage::hash::HashCommonLogType::key_length_, and foedus::storage::hash::HashCommonLogType::payload_count_.

74  {
75  o << "<HashUpdateLogType>"
76  << "<key_length_>" << v.key_length_ << "</key_length_>"
77  << "<key_>" << assorted::Top(v.get_key(), v.key_length_) << "</key_>"
78  << "<bin_bits_>" << static_cast<int>(v.bin_bits_) << "</bin_bits_>"
79  << "<hash_>" << assorted::Hex(v.hash_, 16) << "</hash_>"
80  << "<payload_count_>" << v.payload_count_ << "</payload_count_>"
81  << "<payload_>" << assorted::Top(v.get_payload(), v.payload_count_) << "</payload_>"
82  << "</HashUpdateLogType>";
83  return o;
84 }

Here is the call graph for this function:

std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashOverwriteLogType v 
)

Definition at line 86 of file hash_log_types.cpp.

References foedus::storage::hash::HashCommonLogType::bin_bits_, foedus::storage::hash::HashCommonLogType::get_key(), foedus::storage::hash::HashCommonLogType::get_payload(), foedus::storage::hash::HashCommonLogType::hash_, foedus::storage::hash::HashCommonLogType::key_length_, foedus::storage::hash::HashCommonLogType::payload_count_, and foedus::storage::hash::HashCommonLogType::payload_offset_.

86  {
87  o << "<HashOverwriteLog>"
88  << "<key_length_>" << v.key_length_ << "</key_length_>"
89  << "<key_>" << assorted::Top(v.get_key(), v.key_length_) << "</key_>"
90  << "<bin_bits_>" << static_cast<int>(v.bin_bits_) << "</bin_bits_>"
91  << "<hash_>" << assorted::Hex(v.hash_, 16) << "</hash_>"
92  << "<payload_offset_>" << v.payload_offset_ << "</payload_offset_>"
93  << "<payload_count_>" << v.payload_count_ << "</payload_count_>"
94  << "<payload_>" << assorted::Top(v.get_payload(), v.payload_count_) << "</payload_>"
95  << "</HashOverwriteLog>";
96  return o;
97 }

Here is the call graph for this function:

std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashStorage v 
)

Definition at line 247 of file hash_storage.cpp.

References foedus::storage::hash::HashMetadata::bin_bits_, foedus::Attachable< CONTROL_BLOCK >::control_block_, foedus::storage::Storage< CONTROL_BLOCK >::get_id(), foedus::storage::Storage< CONTROL_BLOCK >::get_name(), and foedus::storage::hash::HashStorageControlBlock::meta_.

247  {
248  o << "<HashStorage>"
249  << "<id>" << v.get_id() << "</id>"
250  << "<name>" << v.get_name() << "</name>"
251  << "<bin_bits>" << static_cast<int>(v.control_block_->meta_.bin_bits_) << "</bin_bits>"
252  << "</HashStorage>";
253  return o;
254 }

Here is the call graph for this function:

std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashTmpBin v 
)

Definition at line 287 of file hash_tmpbin.cpp.

References foedus::storage::hash::HashTmpBin::get_first_record(), foedus::storage::hash::HashTmpBin::Record::get_key(), foedus::storage::hash::HashTmpBin::Record::get_payload(), foedus::storage::hash::HashTmpBin::get_record(), foedus::storage::hash::HashTmpBin::get_records_consumed(), foedus::storage::hash::HashTmpBin::Record::hash_, foedus::storage::hash::HashTmpBin::kBucketCount, foedus::storage::hash::HashTmpBin::Record::key_length_, foedus::storage::hash::HashTmpBin::Record::next_, foedus::storage::hash::HashTmpBin::Record::payload_length_, and foedus::storage::hash::HashTmpBin::Record::xct_id_.

287  {
288  // Each bin shouldn't have that many records... so, output everything!
289  o << "<HashTmpBin>" << std::endl;
290  o << " " << v.memory_ << std::endl;
291  o << " <records_capacity_>" << v.records_capacity_ << "</records_capacity_>" << std::endl;
292  o << " <records_consumed_>" << v.records_consumed_ << "</records_consumed_>" << std::endl;
293  o << " <buckets_>" << std::endl;
294  for (uint32_t i = 0; i < HashTmpBin::kBucketCount; ++i) {
295  if (v.buckets_[i] != 0) {
296  o << " <bucket idx=\"" << i << "\" head_rec=\"" << v.buckets_[i] << "\" />" << std::endl;
297  }
298  }
299  o << " </buckets_>" << std::endl;
300  o << " <records_>" << std::endl;
301  uint32_t begin = v.get_first_record();
302  for (uint32_t i = begin; i < v.get_records_consumed(); ++i) {
303  HashTmpBin::Record* record = v.get_record(i);
304  o << " <record id=\"" << i << "\" hash=\"" << assorted::Hex(record->hash_, 16) << "\"";
305  if (record->next_) {
306  o << " next_rec=\"" << record->next_ << "\"";
307  }
308  o << ">";
309  o << "<key>" << assorted::HexString(std::string(record->get_key(), record->key_length_))
310  << "</key>";
311  o << "<payload>"
312  << assorted::HexString(std::string(record->get_payload(), record->payload_length_))
313  << "</payload>";
314  o << record->xct_id_;
315  o << "</record>" << std::endl;
316  }
317  o << " </records_>" << std::endl;
318  o << "</HashTmpBin>";
319  return o;
320 }

Here is the call graph for this function:

std::ostream& foedus::storage::hash::operator<< ( std::ostream &  o,
const HashPartitioner v 
)

Definition at line 364 of file hash_partitioner_impl.cpp.

References foedus::storage::hash::HashPartitionerData::levels_, and foedus::storage::hash::HashPartitionerData::total_bin_count_.

364  {
365  o << "<HashPartitioner>";
366  if (v.data_) {
367  o << "<levels_>" << static_cast<int>(v.data_->levels_) << "</levels_>"
368  << "<total_bin_count_>" << v.data_->total_bin_count_ << "</total_bin_count_>";
369  } else {
370  o << "Not yet designed";
371  }
372  o << "</HashPartitioner>";
373  return o;
374 }
void foedus::storage::hash::prepare_sort_entries ( uint8_t  bin_shifts,
const Partitioner::SortBatchArguments args,
SortEntry entries 
)

subroutine of sort_batch

Definition at line 236 of file hash_partitioner_impl.cpp.

References ASSERT_ND, foedus::storage::hash::HashCommonLogType::assert_type(), foedus::storage::Partitioner::SortBatchArguments::base_epoch_, foedus::xct::XctId::get_epoch(), foedus::xct::XctId::get_ordinal(), foedus::storage::hash::HashCommonLogType::hash_, foedus::log::BaseLogType::header_, foedus::storage::Partitioner::SortBatchArguments::log_buffer_, foedus::storage::Partitioner::SortBatchArguments::log_positions_, foedus::storage::Partitioner::SortBatchArguments::logs_count_, foedus::snapshot::LogBuffer::resolve(), foedus::storage::hash::SortEntry::set(), foedus::Epoch::subtract(), and foedus::log::LogHeader::xct_id_.

Referenced by foedus::storage::hash::HashPartitioner::sort_batch().

239  {
240  // CPU profile of partition_hash_perf: ??%.
241  const Epoch base_epoch = args.base_epoch_;
242  for (uint32_t i = 0; i < args.logs_count_; ++i) {
243  const HashCommonLogType* log_entry = reinterpret_cast<const HashCommonLogType*>(
244  args.log_buffer_.resolve(args.log_positions_[i]));
245  log_entry->assert_type();
246  Epoch epoch = log_entry->header_.xct_id_.get_epoch();
247  ASSERT_ND(epoch.subtract(base_epoch) < (1U << 16));
248  uint16_t compressed_epoch = epoch.subtract(base_epoch);
249  // this is expensive.. should keep hash in log entries
250  HashValue hash = log_entry->hash_;
251  entries[i].set(
252  hash >> bin_shifts,
253  compressed_epoch,
254  log_entry->header_.xct_id_.get_ordinal(),
255  args.log_positions_[i]);
256  }
257 }
#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
uint64_t HashValue
Represents a full 64-bit hash value calculated from a key.
Definition: hash_id.hpp:129

Here is the call graph for this function:

Here is the caller graph for this function:

void foedus::storage::hash::release_parallel ( Engine engine,
VolatilePagePointer  pointer 
)

Definition at line 260 of file hash_page_impl.cpp.

References ASSERT_ND, foedus::memory::EngineMemory::get_global_volatile_page_resolver(), foedus::Engine::get_memory_manager(), foedus::storage::PageHeader::get_page_type(), foedus::storage::hash::HashIntermediatePage::header(), foedus::storage::kHashIntermediatePageType, foedus::storage::hash::HashIntermediatePage::release_pages_recursive(), and foedus::memory::GlobalVolatilePageResolver::resolve_offset().

Referenced by foedus::storage::hash::HashIntermediatePage::release_pages_recursive_parallel().

260  {
261  const memory::GlobalVolatilePageResolver& page_resolver
262  = engine->get_memory_manager()->get_global_volatile_page_resolver();
263  HashIntermediatePage* p
264  = reinterpret_cast<HashIntermediatePage*>(page_resolver.resolve_offset(pointer));
265  ASSERT_ND(p->header().get_page_type() == kHashIntermediatePageType);
266  memory::PageReleaseBatch release_batch(engine);
267  p->release_pages_recursive(page_resolver, &release_batch);
268  release_batch.release_all();
269 }
#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:

HashDataPage* foedus::storage::hash::resolve_data_impl ( const memory::GlobalVolatilePageResolver resolver,
VolatilePagePointer  pointer 
)
inline

Definition at line 59 of file hash_composer_impl.cpp.

References ASSERT_ND, foedus::storage::construct_volatile_page_pointer(), foedus::storage::PageHeader::get_page_type(), foedus::storage::hash::HashDataPage::header(), foedus::storage::VolatilePagePointer::is_equivalent(), foedus::storage::VolatilePagePointer::is_null(), foedus::storage::kHashDataPageType, foedus::storage::PageHeader::page_id_, and foedus::memory::GlobalVolatilePageResolver::resolve_offset().

61  {
62  if (pointer.is_null()) {
63  return nullptr;
64  }
65  HashDataPage* ret = reinterpret_cast<HashDataPage*>(resolver.resolve_offset(pointer));
66  ASSERT_ND(ret->header().get_page_type() == kHashDataPageType);
67  ASSERT_ND(pointer.is_equivalent(construct_volatile_page_pointer(ret->header().page_id_)));
68  return ret;
69 }
VolatilePagePointer construct_volatile_page_pointer(uint64_t word)
Definition: storage_id.hpp:230
#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:

HashIntermediatePage* foedus::storage::hash::resolve_intermediate_impl ( const memory::GlobalVolatilePageResolver resolver,
VolatilePagePointer  pointer 
)
inline

Definition at line 71 of file hash_composer_impl.cpp.

References ASSERT_ND, foedus::storage::construct_volatile_page_pointer(), foedus::storage::PageHeader::get_page_type(), foedus::storage::hash::HashIntermediatePage::header(), foedus::storage::VolatilePagePointer::is_equivalent(), foedus::storage::VolatilePagePointer::is_null(), foedus::storage::kHashIntermediatePageType, foedus::storage::PageHeader::page_id_, and foedus::memory::GlobalVolatilePageResolver::resolve_offset().

73  {
74  if (pointer.is_null()) {
75  return nullptr;
76  }
77  HashIntermediatePage* ret
78  = reinterpret_cast<HashIntermediatePage*>(resolver.resolve_offset(pointer));
79  ASSERT_ND(ret->header().get_page_type() == kHashIntermediatePageType);
80  ASSERT_ND(pointer.is_equivalent(construct_volatile_page_pointer(ret->header().page_id_)));
81  return ret;
82 }
VolatilePagePointer construct_volatile_page_pointer(uint64_t word)
Definition: storage_id.hpp:230
#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:

Variable Documentation

const uint64_t foedus::storage::hash::kFanout64 = kHashIntermediatePageFanout

just to write the following concisely

Definition at line 65 of file hash_id.hpp.

const uint16_t foedus::storage::hash::kHashComposedBinsPageMaxBins = (kPageSize - 80) / sizeof(ComposedBin)

Definition at line 90 of file hash_composed_bins_impl.hpp.

const HashValue foedus::storage::hash::kHashDataPageBloomFilterIndexMask = (1U << kHashDataPageBloomFilterIndexSize) - 1U
const HashBin foedus::storage::hash::kInvalidHashBin = 1ULL << kHashMaxBinBits