FlashGraph-ng
A new frontier in large-scale graph analysis and data mining
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
NUMA_cache.h
1 #ifndef __NUMA_CACHE_H__
2 #define __NUMA_CACHE_H__
3 
4 /*
5  * Copyright 2014 Open Connectome Project (http://openconnecto.me)
6  * Written by Da Zheng (zhengda1936@gmail.com)
7  *
8  * This file is part of SAFSlib.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 
23 #include <tr1/unordered_map>
24 #include <vector>
25 
26 #include "cache.h"
27 #include "cache_config.h"
28 
29 namespace safs
30 {
31 
32 /*
33  * This cache divides a global cache to pieces of the same size,
34  * and place them on the specified NUMA nodes.
35  */
36 class NUMA_cache: public page_cache
37 {
38  const cache_config *cache_conf;
39  std::vector<page_cache::ptr> caches;
40 
41  NUMA_cache(const cache_config *config, int max_num_pending_flush): caches(
42  config->get_num_cache_parts()) {
43  cache_conf = config;
44  std::vector<int> node_ids;
45  cache_conf->get_node_ids(node_ids);
46  cache_conf->create_cache_on_nodes(node_ids,
47  max_num_pending_flush / node_ids.size(), caches);
48  }
49 public:
50  static page_cache::ptr create(const cache_config *config,
51  int max_num_pending_flush) {
52  return page_cache::ptr(new NUMA_cache(config, max_num_pending_flush));
53  }
54 
55  page_cache &get_cache_on_node(int node_id) const {
56  return *caches[node_id];
57  }
58 
59  virtual page *search(const page_id_t &pg_id, page_id_t &old_id) {
60  int idx = cache_conf->page2cache(pg_id);
61  return caches[idx]->search(pg_id, old_id);
62  }
63 
64  virtual page *search(const page_id_t &pg_id) {
65  int idx = cache_conf->page2cache(pg_id);
66  return caches[idx]->search(pg_id);
67  }
68 
69  virtual long size() {
70  return cache_conf->get_size();
71  }
72 
73  // TODO shouldn't I use a different underlying IO for cache
74  // on the different nodes.
75  virtual void init(std::shared_ptr<io_interface> underlying) {
76  for (size_t i = 0; i < caches.size(); i++) {
77  // TODO this is a ugly hack. It makes sure that each flush
78  // thread of a SA-cache has a reference to this NUMA cache.
79  caches[i]->create_flusher(underlying, this);
80  caches[i]->init(underlying);
81  }
82  }
83 
84  virtual void print_stat() const {
85  for (size_t i = 0; i < caches.size(); i++)
86  caches[i]->print_stat();
87  }
88 
89  virtual void mark_dirty_pages(thread_safe_page *pages[], int num,
90  io_interface &io) {
91  for (int i = 0; i < num; i++) {
92  page_id_t pg_id(pages[i]->get_file_id(), pages[i]->get_offset());
93  int idx = cache_conf->page2cache(pg_id);
94  caches[idx]->mark_dirty_pages(&pages[i], 1, io);
95  }
96  }
97 
98  virtual void flush_callback(io_request &req) {
99  assert(req.within_1page());
100  page_id_t pg_id(req.get_file_id(), req.get_offset());
101  int idx = cache_conf->page2cache(pg_id);
102  caches[idx]->flush_callback(req);
103  }
104 
105  virtual int flush_dirty_pages(page_filter *filter, int max_num) {
106  int tot = 0;
107  for (size_t i = 0; i < caches.size(); i++) {
108  tot += caches[i]->flush_dirty_pages(filter,
109  max_num / caches.size());
110  }
111  return tot;
112  }
113 
114  virtual void sanity_check() const {
115  for (size_t i = 0; i < caches.size(); i++) {
116  caches[i]->sanity_check();
117  }
118  }
119 };
120 
121 }
122 
123 #endif