libfoedus-core
FOEDUS Core Library
array_storage_pimpl.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_ARRAY_ARRAY_STORAGE_PIMPL_HPP_
19 #define FOEDUS_STORAGE_ARRAY_ARRAY_STORAGE_PIMPL_HPP_
20 #include <stdint.h>
21 
22 #include <string>
23 #include <vector>
24 
25 #include "foedus/attachable.hpp"
26 #include "foedus/compiler.hpp"
27 #include "foedus/cxx11.hpp"
28 #include "foedus/fwd.hpp"
30 #include "foedus/memory/fwd.hpp"
32 #include "foedus/storage/fwd.hpp"
41 #include "foedus/thread/fwd.hpp"
42 #include "foedus/thread/thread.hpp"
43 
44 namespace foedus {
45 namespace storage {
46 namespace array {
49  // this is backed by shared memory. not instantiation. just reinterpret_cast.
50  ArrayStorageControlBlock() = delete;
51  ~ArrayStorageControlBlock() = delete;
52 
53  bool exists() const { return status_ == kExists || status_ == kMarkedForDeath; }
54 
62 
63  // Do NOT reorder members up to here. The layout must be compatible with StorageControlBlock
64  // Type-specific shared members below.
65 
67  uint8_t levels_;
69 
78  uint64_t intervals_[8];
79 };
80 
88 class ArrayStoragePimpl final {
89  public:
90  enum Constants {
92  kBatchMax = 16,
93  };
94 
95  ArrayStoragePimpl() = delete;
96  explicit ArrayStoragePimpl(ArrayStorage* storage)
97  : engine_(storage->get_engine()), control_block_(storage->get_control_block()) {}
99  : engine_(engine), control_block_(control_block) {}
100 
102 
103  ErrorStack create(const Metadata& metadata);
104  ErrorStack load(const StorageControlBlock& snapshot_block);
106 
108 
109  bool exists() const { return control_block_->exists(); }
110  const ArrayMetadata& get_meta() const { return control_block_->meta_; }
111  StorageId get_id() const { return get_meta().id_; }
112  uint16_t get_levels() const { return control_block_->levels_; }
115  }
116  uint16_t get_payload_size() const { return get_meta().payload_size_; }
118  ErrorCode get_root_page(thread::Thread* context, bool for_write, ArrayPage** out) ALWAYS_INLINE;
121 
124 
127  thread::Thread* context,
128  bool install_volatile,
129  bool cache_snapshot,
130  ArrayOffset from,
131  ArrayOffset to);
133  thread::Thread* context,
134  bool install_volatile,
135  bool cache_snapshot,
136  ArrayOffset from,
137  ArrayOffset to,
138  ArrayPage* page);
139 
140  // all per-record APIs are called so frequently, so returns ErrorCode rather than ErrorStack
142  thread::Thread* context,
143  ArrayOffset offset,
144  Record** out,
145  bool* snapshot_record) ALWAYS_INLINE;
146 
148  thread::Thread* context,
149  ArrayOffset offset,
150  Record** out) ALWAYS_INLINE;
151 
153  thread::Thread* context,
154  ArrayOffset offset,
155  void *payload,
156  uint16_t payload_offset,
157  uint16_t payload_count) ALWAYS_INLINE;
158 
159  template <typename T>
161  thread::Thread* context,
162  ArrayOffset offset,
163  T *payload,
164  uint16_t payload_offset);
165 
167  thread::Thread* context,
168  ArrayOffset offset,
169  const void **payload) ALWAYS_INLINE;
171  thread::Thread* context,
172  ArrayOffset offset,
173  Record** record) ALWAYS_INLINE;
174 
175  template <typename T>
177  thread::Thread* context,
178  uint16_t payload_offset,
179  uint16_t batch_size,
180  const ArrayOffset* offset_batch,
181  T* payload_batch) ALWAYS_INLINE;
183  thread::Thread* context,
184  uint16_t batch_size,
185  const ArrayOffset* offset_batch,
186  const void** payload_batch) ALWAYS_INLINE;
188  thread::Thread* context,
189  uint16_t batch_size,
190  const ArrayOffset* offset_batch,
191  Record** record_batch) ALWAYS_INLINE;
192 
194  const void *payload, uint16_t payload_offset, uint16_t payload_count) ALWAYS_INLINE;
195  template <typename T>
197  T payload, uint16_t payload_offset);
198 
200  thread::Thread* context,
201  ArrayOffset offset,
202  Record* record,
203  const void *payload,
204  uint16_t payload_offset,
205  uint16_t payload_count) ALWAYS_INLINE;
206 
207  template <typename T>
209  thread::Thread* context,
210  ArrayOffset offset,
211  Record* record,
212  T payload,
213  uint16_t payload_offset) ALWAYS_INLINE;
214 
215  template <typename T>
217  T* value, uint16_t payload_offset);
218  template <typename T>
220  thread::Thread* context,
221  ArrayOffset offset,
222  T value,
223  uint16_t payload_offset);
224 
226  thread::Thread* context,
227  ArrayOffset offset,
228  ArrayPage** out,
229  uint16_t* index,
230  bool* snapshot_page) ALWAYS_INLINE;
231 
236  thread::Thread* context,
237  ArrayOffset offset,
238  ArrayPage** out,
239  uint16_t* index) ALWAYS_INLINE;
240 
241  // the following methods are for batching. no point to do ALWAYS_INLINE
243  thread::Thread* context,
244  uint16_t batch_size,
245  const ArrayOffset* offset_batch,
246  Record** out_batch,
247  bool* snapshot_page_batch);
249  thread::Thread* context,
250  uint16_t batch_size,
251  const ArrayOffset* offset_batch,
252  ArrayPage** out_batch,
253  uint16_t* index_batch,
254  bool* snapshot_page_batch);
256  thread::Thread* context,
257  uint16_t batch_size,
258  const ArrayOffset* offset_batch,
259  Record** record_batch);
260 
262  static void release_pages_recursive(
263  const memory::GlobalVolatilePageResolver& resolver,
265  VolatilePagePointer volatile_page_id);
266 
271  static std::vector<uint64_t> calculate_required_pages(uint64_t array_size, uint16_t payload);
276  static std::vector<uint64_t> calculate_offset_intervals(uint8_t levels, uint16_t payload);
277 
279  thread::Thread* context,
280  bool in_snapshot,
281  bool for_write,
282  DualPagePointer* pointer,
283  ArrayPage** out,
284  const ArrayPage* parent,
285  uint16_t index_in_parent) ALWAYS_INLINE;
287  thread::Thread* context,
288  uint16_t batch_size,
289  bool* in_snapshot,
290  ArrayPage** parents,
291  const uint16_t* index_in_parents,
292  ArrayPage** out);
294  thread::Thread* context,
295  uint16_t batch_size,
296  ArrayPage** parents,
297  const uint16_t* index_in_parents,
298  ArrayPage** out);
299 
300  Engine* const engine_;
302 };
303 
305  thread::Thread* context,
306  bool in_snapshot,
307  bool for_write,
308  DualPagePointer* pointer,
309  ArrayPage** out,
310  const ArrayPage* parent,
311  uint16_t index_in_parent) {
312  ASSERT_ND(!in_snapshot || !for_write); // if we are modifying, we must be in volatile world
313  ASSERT_ND(!parent->is_leaf());
315  array_volatile_page_init, // array might have null pointer. in that case create empty new page
316  false, // if both volatile/snapshot null, create a new volatile (logically all-zero)
317  for_write,
318  !in_snapshot, // if we are already in snapshot world, no need to take more pointer set
319  pointer,
320  reinterpret_cast<Page**>(out),
321  reinterpret_cast<const Page*>(parent),
322  index_in_parent));
323 
324 #ifndef NDEBUG
325  ArrayPage* page = *out;
326  ASSERT_ND(page != nullptr);
327  ASSERT_ND(page->get_level() + 1U == parent->get_level());
328  if (page->is_leaf()) {
329  xct::XctId xct_id = page->get_leaf_record(0, get_payload_size())->owner_id_.xct_id_;
330  ASSERT_ND(xct_id.is_valid());
331  }
332 #endif // NDEBUG
333  return kErrorCodeOk;
334 }
335 
336 
338  thread::Thread* context,
339  bool for_write,
340  ArrayPage** out) {
341  return context->follow_page_pointer(
342  nullptr,
343  false,
344  for_write,
345  true,
347  reinterpret_cast<Page**>(out),
348  nullptr,
349  0);
350 }
351 
352 
353 static_assert(sizeof(ArrayStoragePimpl) <= kPageSize, "ArrayStoragePimpl is too large");
354 static_assert(
356  "ArrayStorageControlBlock is too large.");
357 
358 } // namespace array
359 } // namespace storage
360 } // namespace foedus
361 #endif // FOEDUS_STORAGE_ARRAY_ARRAY_STORAGE_PIMPL_HPP_
362 
ErrorStack verify_single_thread(thread::Thread *context)
ErrorCode locate_record_for_read_batch(thread::Thread *context, uint16_t batch_size, const ArrayOffset *offset_batch, Record **out_batch, bool *snapshot_page_batch)
ErrorCode locate_record_for_read(thread::Thread *context, ArrayOffset offset, Record **out, bool *snapshot_record) __attribute__((always_inline))
Represents one record in our key-value store.
Definition: record.hpp:33
StorageStatus status_
Status of the storage.
Represents a pointer to another page (usually a child page).
Definition: storage_id.hpp:271
The storage has been marked for drop and can't be used.
Definition: storage_id.hpp:164
Definitions of IDs in this package and a few related constant values.
ErrorCode follow_pointers_for_write_batch(thread::Thread *context, uint16_t batch_size, ArrayPage **parents, const uint16_t *index_in_parents, ArrayPage **out)
ArrayOffset array_size_
Size of this array.
ErrorCode get_record_for_write(thread::Thread *context, ArrayOffset offset, Record **record) __attribute__((always_inline))
ErrorCode get_record(thread::Thread *context, ArrayOffset offset, void *payload, uint16_t payload_offset, uint16_t payload_count) __attribute__((always_inline))
uint32_t StorageId
Unique ID for storage.
Definition: storage_id.hpp:55
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
ErrorCode lookup_for_read_batch(thread::Thread *context, uint16_t batch_size, const ArrayOffset *offset_batch, ArrayPage **out_batch, uint16_t *index_batch, bool *snapshot_page_batch)
Represents a key-value store based on a dense and regular array.
ErrorCode locate_record_for_write(thread::Thread *context, ArrayOffset offset, Record **out) __attribute__((always_inline))
Represents one thread running on one NUMA core.
Definition: thread.hpp:48
uint64_t intervals_[8]
intervals_[x] is the range of array offset in one page of level-x.
uint64_t ArrayOffset
The only key type in array storage.
Definition: array_id.hpp:48
Represents a pointer to a volatile page with modification count for preventing ABA.
Definition: storage_id.hpp:194
Forward declarations of classes in root package.
Persistent status part of Transaction ID.
Definition: xct_id.hpp:955
ErrorCode get_record_primitive(thread::Thread *context, ArrayOffset offset, T *payload, uint16_t payload_offset)
Brings error stacktrace information as return value of functions.
Definition: error_stack.hpp:81
Represents one data page in Array Storage.
void array_volatile_page_init(const VolatilePageInitArguments &args)
volatile page initialize callback for ArrayPage.
The storage has been created and ready for use.
Definition: storage_id.hpp:158
ErrorCode get_record_payload(thread::Thread *context, ArrayOffset offset, const void **payload) __attribute__((always_inline))
Forward declarations of classes in array storage package.
ErrorCode get_root_page(thread::Thread *context, bool for_write, ArrayPage **out) __attribute__((always_inline))
ErrorCode follow_page_pointer(storage::VolatilePageInit page_initializer, bool tolerate_null_pointer, bool will_modify, bool take_ptr_set_snapshot, storage::DualPagePointer *pointer, storage::Page **page, const storage::Page *parent, uint16_t index_in_parent)
A general method to follow (read) a page pointer.
bool is_valid() const __attribute__((always_inline))
Definition: xct_id.hpp:973
A mutex that can be placed in shared memory and used from multiple processes.
Metadata of one storage.
Definition: metadata.hpp:58
ErrorCode lookup_for_write(thread::Thread *context, ArrayOffset offset, ArrayPage **out, uint16_t *index) __attribute__((always_inline))
This version always returns a volatile page, installing a new one if needed.
ErrorCode increment_record(thread::Thread *context, ArrayOffset offset, T *value, uint16_t payload_offset)
DualPagePointer root_page_pointer_
Points to the root page (or something equivalent).
If you want more than this, you should loop.
ErrorCode overwrite_record(thread::Thread *context, ArrayOffset offset, const void *payload, uint16_t payload_offset, uint16_t payload_count) __attribute__((always_inline))
ArrayMetadata meta_
metadata of this storage.
0 means no-error.
Definition: error_code.hpp:87
ErrorCode lookup_for_read(thread::Thread *context, ArrayOffset offset, ArrayPage **out, uint16_t *index, bool *snapshot_page) __attribute__((always_inline))
ErrorCode prefetch_pages(thread::Thread *context, bool install_volatile, bool cache_snapshot, ArrayOffset from, ArrayOffset to)
defined in array_storage_prefetch.cpp
Forward declarations of classes in storage package.
A helper class to return a bunch of pages to individual nodes.
Definition: page_pool.hpp:276
ArrayStorageControlBlock *const control_block_
Database engine object that holds all resources and provides APIs.
Definition: engine.hpp:109
ErrorCode get_record_for_write_batch(thread::Thread *context, uint16_t batch_size, const ArrayOffset *offset_batch, Record **record_batch) __attribute__((always_inline))
ErrorCode follow_pointers_for_read_batch(thread::Thread *context, uint16_t batch_size, bool *in_snapshot, ArrayPage **parents, const uint16_t *index_in_parents, ArrayPage **out)
Metadata of an array storage.
static std::vector< uint64_t > calculate_required_pages(uint64_t array_size, uint16_t payload)
Calculate leaf/interior pages we need.
static void release_pages_recursive(const memory::GlobalVolatilePageResolver &resolver, memory::PageReleaseBatch *batch, VolatilePagePointer volatile_page_id)
Used only from drop()
static std::vector< uint64_t > calculate_offset_intervals(uint8_t levels, uint16_t payload)
The offset interval a single page represents in each level.
Forward declarations of classes in memory package.
ArrayStoragePimpl(Engine *engine, ArrayStorageControlBlock *control_block)
ErrorCode lookup_for_write_batch(thread::Thread *context, uint16_t batch_size, const ArrayOffset *offset_batch, Record **record_batch)
ErrorStack load(const StorageControlBlock &snapshot_block)
ErrorStack hcc_reset_all_temperature_stat_intermediate(VolatilePagePointer intermediate_page_id)
#define CHECK_ERROR_CODE(x)
This macro calls x and checks its returned error code.
Definition: error_code.hpp:155
Packages logic and required properties to calculate LookupRoute in array storage from offset...
Definition: array_route.hpp:86
ErrorCode follow_pointer(thread::Thread *context, bool in_snapshot, bool for_write, DualPagePointer *pointer, ArrayPage **out, const ArrayPage *parent, uint16_t index_in_parent) __attribute__((always_inline))
ErrorCode increment_record_oneshot(thread::Thread *context, ArrayOffset offset, T value, uint16_t payload_offset)
Resolves an offset in a volatile page pool to an actual pointer and vice versa.
Definitions of IDs in this package and a few related constant values.
ErrorCode get_record_primitive_batch(thread::Thread *context, uint16_t payload_offset, uint16_t batch_size, const ArrayOffset *offset_batch, T *payload_batch) __attribute__((always_inline))
uint16_t snapshot_drop_volatile_pages_threshold_
Number of levels of volatile pages to keep after each snapshotting.
#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
Forward declarations of classes in thread package.
ErrorCode get_record_payload_batch(thread::Thread *context, uint16_t batch_size, const ArrayOffset *offset_batch, const void **payload_batch) __attribute__((always_inline))
ErrorStack create(const Metadata &metadata)
#define ALWAYS_INLINE
A function suffix to hint that the function should always be inlined.
Definition: compiler.hpp:106
A base layout of shared data for all storage types.
Definition: storage.hpp:53
StorageId id_
the unique ID of this storage.
Definition: metadata.hpp:103
uint16_t payload_size_
byte size of one record in this array storage without internal overheads
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 prefetch_pages_recurse(thread::Thread *context, bool install_volatile, bool cache_snapshot, ArrayOffset from, ArrayOffset to, ArrayPage *page)
ErrorCode overwrite_record_primitive(thread::Thread *context, ArrayOffset offset, T payload, uint16_t payload_offset)
StorageStatus
Status of a storage.
Definition: storage_id.hpp:154