libfoedus-core
FOEDUS Core Library
array_storage_prefetch.cpp
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  */
19 
20 #include <glog/logging.h>
21 
22 #include "foedus/assert_nd.hpp"
26 #include "foedus/thread/thread.hpp"
27 
28 namespace foedus {
29 namespace storage {
30 namespace array {
32  thread::Thread* context,
33  bool vol_on,
34  bool snp_on,
35  ArrayOffset from,
36  ArrayOffset to) {
38  VLOG(0) << "Thread-" << context->get_thread_id()
39  << " prefetching " << get_meta().name_ << " from=" << from << ", to=" << to;
40  ArrayPage* root_page;
41  CHECK_ERROR_CODE(get_root_page(context, vol_on, &root_page));
42  prefetch_page_l2(root_page);
43  if (!root_page->is_leaf()) {
44  CHECK_ERROR_CODE(prefetch_pages_recurse(context, vol_on, snp_on, from, to, root_page));
45  }
46 
47  watch.stop();
48  VLOG(0) << "Thread-" << context->get_thread_id()
49  << " prefetched " << get_meta().name_ << " in " << watch.elapsed_us() << "us";
50  return kErrorCodeOk;
51 }
52 
54  thread::Thread* context,
55  bool vol_on,
56  bool snp_on,
57  ArrayOffset from,
58  ArrayOffset to,
59  ArrayPage* page) {
60  ASSERT_ND(!page->header().snapshot_ || !vol_on);
61  uint8_t level = page->get_level();
62  ASSERT_ND(level > 0);
64  for (uint8_t i = 1; i < level; ++i) {
65  interval *= kInteriorFanout;
66  }
67  bool in_snapshot = page->header().snapshot_;
68  ArrayRange page_range = page->get_array_range();
69  ArrayRange range(from, to);
70  ASSERT_ND(page_range.overlaps(range)); // otherwise why we came here...
71  ASSERT_ND(page_range.begin_ + (interval * kInteriorFanout) >= page_range.end_); // probably==
72  for (uint16_t i = 0; i < kInteriorFanout; ++i) {
73  ArrayRange child_range(
74  page_range.begin_ + i * interval,
75  page_range.begin_ + (i + 1U) * interval);
76  if (!range.overlaps(child_range)) {
77  continue;
78  }
79 
80  DualPagePointer& pointer = page->get_interior_record(i);
81 
82  // first, do we have to cache snapshot page?
83  if (pointer.snapshot_pointer_ != 0) {
84  if (snp_on) {
85  ArrayPage* child;
87  pointer.snapshot_pointer_,
88  reinterpret_cast<Page**>(&child)));
89  ASSERT_ND(child->get_array_range().begin_ == page_range.begin_ + i * interval);
90  ASSERT_ND(range.overlaps(child->get_array_range()));
91  prefetch_page_l2(child);
92  if (level > 1U) {
93  CHECK_ERROR_CODE(prefetch_pages_recurse(context, false, snp_on, from, to, child));
94  }
95  }
96  // do we have to install volatile page based on it?
97  if (pointer.volatile_pointer_.is_null() && vol_on && !in_snapshot) {
98  ArrayPage* child;
100  &pointer,
101  reinterpret_cast<Page**>(&child)));
102  ASSERT_ND(child->get_array_range().begin_ == page_range.begin_ + i * interval);
103  ASSERT_ND(range.overlaps(child->get_array_range()));
104  }
105  }
106 
107  // then go down
108  if (vol_on && !pointer.volatile_pointer_.is_null()) {
109  ASSERT_ND(!in_snapshot);
110  ArrayPage* child = context->resolve_cast<ArrayPage>(pointer.volatile_pointer_);
111  ASSERT_ND(child->get_array_range().begin_ == page_range.begin_ + i * interval);
112  ASSERT_ND(range.overlaps(child->get_array_range()));
113  prefetch_page_l2(child);
114  if (level > 1U) {
115  CHECK_ERROR_CODE(prefetch_pages_recurse(context, vol_on, snp_on, from, to, child));
116  }
117  }
118  }
119  return kErrorCodeOk;
120 }
121 
122 } // namespace array
123 } // namespace storage
124 } // namespace foedus
ErrorCode find_or_read_a_snapshot_page(storage::SnapshotPagePointer page_id, storage::Page **out)
Find the given page in snapshot cache, reading it if not found.
Definition: thread.cpp:95
ErrorCode install_a_volatile_page(storage::DualPagePointer *pointer, storage::Page **installed_page)
Installs a volatile page to the given dual pointer as a copy of the snapshot page.
Definition: thread.cpp:107
Represents a pointer to another page (usually a child page).
Definition: storage_id.hpp:271
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
uint64_t ArrayOffset
The only key type in array storage.
Definition: array_id.hpp:48
ThreadId get_thread_id() const
Definition: thread.cpp:53
Represents one data page in Array Storage.
ErrorCode get_root_page(thread::Thread *context, bool for_write, ArrayPage **out) __attribute__((always_inline))
ArrayOffset begin_
Inclusive beginning of the offset range.
Definition: array_id.hpp:86
VolatilePagePointer volatile_pointer_
Definition: storage_id.hpp:308
0 means no-error.
Definition: error_code.hpp:87
const DualPagePointer & get_interior_record(uint16_t record) const __attribute__((always_inline))
const ArrayRange & get_array_range() const
ErrorCode prefetch_pages(thread::Thread *context, bool install_volatile, bool cache_snapshot, ArrayOffset from, ArrayOffset to)
defined in array_storage_prefetch.cpp
ArrayOffset end_
Exclusive end of the offset range.
Definition: array_id.hpp:88
ArrayStorageControlBlock *const control_block_
uint64_t stop()
Take another current time tick.
Definition: stop_watch.cpp:35
void prefetch_page_l2(const void *page)
Prefetch a page to L2/L3 cache.
bool overlaps(const ArrayRange &other) const
Returns if there is any overlap with the other range.
Definition: array_id.hpp:74
SnapshotPagePointer snapshot_pointer_
Definition: storage_id.hpp:307
StorageName name_
the unique name of this storage.
Definition: metadata.hpp:107
P * resolve_cast(storage::VolatilePagePointer ptr) const
resolve() plus reinterpret_cast
Definition: thread.hpp:110
double elapsed_us() const
Definition: stop_watch.hpp:45
Represents an offset range in an array storage.
Definition: array_id.hpp:62
#define CHECK_ERROR_CODE(x)
This macro calls x and checks its returned error code.
Definition: error_code.hpp:155
uint16_t get_records_in_leaf() const __attribute__((always_inline))
bool snapshot_
Whether this page image is of a snapshot page.
Definition: page.hpp:211
const uint16_t kInteriorFanout
Max number of entries in an interior page of array storage.
Definition: array_id.hpp:110
#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
A high-resolution stop watch.
Definition: stop_watch.hpp:30
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)