20 #include <glog/logging.h>
33 : memory_(), records_capacity_(0), records_consumed_(0), buckets_(nullptr), records_(nullptr) {
57 memory_ = std::move(*provider);
66 *recipient = std::move(memory_);
77 std::memset(buckets_, 0, records_consumed_ *
sizeof(
Record));
93 buckets_[extract_bucket(record->
hash_)] = 0;
99 void HashTmpBin::on_memory_set() {
103 records_capacity_ = 0;
112 inline ErrorCode HashTmpBin::alloc_record(RecordIndex* out) {
113 if (
UNLIKELY(records_consumed_ == records_capacity_)) {
115 LOG(INFO) <<
"We need to resize HashTmpBin! current_size=" << memory_.
get_size();
120 ASSERT_ND(records_consumed_ < records_capacity_);
121 *out = records_consumed_;
132 uint16_t payload_length) {
135 SearchResult result = search_bucket(key, key_length, hash);
136 if (result.found_ == 0) {
140 record->
set_all(xct_id, key, key_length, hash, payload, payload_length);
142 if (result.tail_ == 0) {
143 uint16_t bucket_index = extract_bucket(hash);
145 buckets_[bucket_index] = new_index;
147 ASSERT_ND(buckets_[extract_bucket(hash)] != 0);
149 tail_record->
next_ = new_index;
155 DLOG(WARNING) <<
"HashTmpBin::insert_record() hit KeyAlreadyExists case. This must not"
156 <<
" happen except unit testcases.";
174 SearchResult result = search_bucket(key, key_length, hash);
176 DLOG(WARNING) <<
"HashTmpBin::delete_record() hit KeyNotFound case 1. This must not"
177 <<
" happen except unit testcases.";
183 DLOG(WARNING) <<
"HashTmpBin::delete_record() hit KeyNotFound case 2. This must not"
184 <<
" happen except unit testcases.";
200 uint16_t payload_offset,
201 uint16_t payload_count) {
204 SearchResult result = search_bucket(key, key_length, hash);
206 DLOG(WARNING) <<
"HashTmpBin::overwrite_record() hit KeyNotFound case 1. This must not"
207 <<
" happen except unit testcases.";
213 DLOG(WARNING) <<
"HashTmpBin::overwrite_record() hit KeyNotFound case 2. This must not"
214 <<
" happen except unit testcases.";
217 DLOG(WARNING) <<
"HashTmpBin::overwrite_record() hit TooShortPayload case. This must not"
218 <<
" happen except unit testcases.";
235 uint16_t payload_length) {
238 SearchResult result = search_bucket(key, key_length, hash);
240 DLOG(WARNING) <<
"HashTmpBin::update_record() hit KeyNotFound case 1. This must not"
241 <<
" happen except unit testcases.";
247 DLOG(WARNING) <<
"HashTmpBin::update_record() hit KeyNotFound case 2. This must not"
248 <<
" happen except unit testcases.";
260 inline HashTmpBin::SearchResult HashTmpBin::search_bucket(
264 uint16_t bucket_index = extract_bucket(hash);
267 return SearchResult(0, 0);
274 if (record->hash_ == hash && record->key_length_ == key_length) {
275 if (
LIKELY(std::memcmp(record->get_key(), key, key_length) == 0)) {
276 return SearchResult(cur, 0);
284 return SearchResult(0, last_seen);
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;
295 if (v.buckets_[i] != 0) {
296 o <<
" <bucket idx=\"" << i <<
"\" head_rec=\"" << v.buckets_[i] <<
"\" />" << std::endl;
299 o <<
" </buckets_>" << std::endl;
300 o <<
" <records_>" << std::endl;
304 o <<
" <record id=\"" << i <<
"\" hash=\"" <<
assorted::Hex(record->
hash_, 16) <<
"\"";
306 o <<
" next_rec=\"" << record->
next_ <<
"\"";
315 o <<
"</record>" << std::endl;
317 o <<
" </records_>" << std::endl;
318 o <<
"</HashTmpBin>";
0x080A : "STORAGE: The record's payload is smaller than requested" .
Represents one record in our key-value store.
numa_alloc_onnode() and numa_free().
0x080C : "STORAGE: This key is not found in this storage" .
ErrorCode create_memory(uint16_t numa_node, uint64_t initial_size=kDefaultInitialSize)
Allocates the memory to use by this object.
void release_block()
Releases the memory block.
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
uint32_t RecordIndex
Pointer to Record.
void clean()
Removes all tuple data for the current bin.
ErrorCode update_record(xct::XctId xct_id, const void *key, uint16_t key_length, HashValue hash, const void *payload, uint16_t payload_length)
Updates a record of the given key with the given payload, which might change length.
void set_all(xct::XctId xct_id, const void *key, uint16_t key_length, HashValue hash, const void *payload, uint16_t payload_length) __attribute__((always_inline))
void steal_memory(memory::AlignedMemory *provider)
This is a special version of create_memory() where this object steals the memory ownership from the r...
An in-memory single-threaded data structure to compose tuples in a hash bin.
Persistent status part of Transaction ID.
ErrorCode assure_capacity(uint64_t required_size, double expand_margin=2.0, bool retain_content=false) noexcept
If the current size is smaller than the given size, automatically expands.
void clean_quick()
This version selectively clears buckets_ by seeing individual records.
void alloc(uint64_t size, uint64_t alignment, AllocType alloc_type, int numa_node) noexcept
Allocate a memory, releasing the current memory if exists.
#define LIKELY(x)
Hints that x is highly likely true.
HashTmpBin()
Constructor doesn't do any initialization.
void overwrite_payload(const void *payload, uint16_t payload_offset, uint16_t payload_count) __attribute__((always_inline))
HashValue hashinate(const void *key, uint16_t key_length)
Calculates hash value for general input.
std::ostream & operator<<(std::ostream &o, const HashCombo &v)
RecordIndex get_records_consumed() const
char * get_payload() __attribute__((always_inline))
This is a per-bin data structure.
char * get_key() __attribute__((always_inline))
ErrorCode delete_record(xct::XctId xct_id, const void *key, uint16_t key_length, HashValue hash)
Logically deletes a record of the given key.
bool is_deleted() const __attribute__((always_inline))
Equivalent to std::hex in case the stream doesn't support it.
void * get_block() const
Returns the memory block.
Record * get_record(RecordIndex index) const
void set_payload(const void *payload, uint16_t payload_length) __attribute__((always_inline))
uint64_t get_size() const
Returns the byte size of the memory block.
ErrorCode insert_record(xct::XctId xct_id, const void *key, uint16_t key_length, HashValue hash, const void *payload, uint16_t payload_length)
Inserts a new record of the given key and payload.
#define CHECK_ERROR_CODE(x)
This macro calls x and checks its returned error code.
ErrorCode overwrite_record(xct::XctId xct_id, const void *key, uint16_t key_length, HashValue hash, const void *payload, uint16_t payload_offset, uint16_t payload_count)
Overwrites a part of the record of the given key.
void give_memory(memory::AlignedMemory *recipient)
This is a special version of release_memory() where this object moves the memory ownership to the rec...
Represents one memory block aligned to actual OS/hardware pages.
RecordIndex next_
constitutes a singly-linked list in each bucket
Represents a record with a unique key.
Convenient way of writing hex integers to stream.
void release_memory()
Destructor automatically releases everything, but you can use this to do it earlier.
RecordIndex get_first_record() const
#define UNLIKELY(x)
Hints that x is highly likely false.
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
const uint16_t kPageSize
A constant defining the page size (in bytes) of both snapshot pages and volatile pages.
ErrorCode
Enum of error codes defined in error_code.xmacro.
int compare_epoch_and_orginal(const XctId &other) const __attribute__((always_inline))
Returns -1, 0, 1 when this is less than, same, larger than other in terms of epoch/ordinal.
0x080B : "STORAGE: This key already exists in this storage" .
uint64_t HashValue
Represents a full 64-bit hash value calculated from a key.
bool is_null() const
Returns if this object doesn't hold a valid memory block.