0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
QueryCache.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2015 Hypertable, Inc.
3  *
4  * This file is part of Hypertable.
5  *
6  * Hypertable is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; version 3 of the
9  * License, or any later version.
10  *
11  * Hypertable is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 
22 #include <Common/Compat.h>
23 #include "QueryCache.h"
24 
25 #include <Hypertable/Lib/Key.h>
27 
28 #include <Common/Config.h>
29 
30 #include <cassert>
31 #include <iostream>
32 #include <vector>
33 
34 using namespace Hypertable;
35 using namespace Hypertable::Config;
36 using namespace std;
37 
38 #define OVERHEAD 64
39 
40 QueryCache::QueryCache(uint64_t max_memory)
41  : m_max_memory(max_memory), m_avail_memory(max_memory) {
43  m_mutex.set_statistics_enabled(properties->get_bool("Hypertable.RangeServer.QueryCache.EnableMutexStatistics"));
44 }
45 
46 bool
47 QueryCache::insert(Key *key, const char *tablename, const char *row,
48  std::set<uint8_t> &columns, uint32_t cell_count,
49  boost::shared_array<uint8_t> &result,
50  uint32_t result_length) {
51  lock_guard<MutexWithStatistics> lock(m_mutex);
52  LookupHashIndex &hash_index = m_cache.get<1>();
53  LookupHashIndex::iterator lookup_iter;
54  uint64_t length = result_length + OVERHEAD + strlen(row);
55 
56  if (length > m_max_memory)
57  return false;
58 
59  if ((lookup_iter = hash_index.find(*key)) != hash_index.end()) {
60  m_avail_memory += (*lookup_iter).result_length + OVERHEAD + strlen((*lookup_iter).row_key.row);
61  hash_index.erase(lookup_iter);
62  }
63 
64  // make room
65  if (m_avail_memory < length) {
66  Cache::iterator iter = m_cache.begin();
67  while (iter != m_cache.end()) {
68  m_avail_memory += (*iter).result_length + OVERHEAD + strlen((*iter).row_key.row);
69  iter = m_cache.erase(iter);
70  if (m_avail_memory >= length)
71  break;
72  }
73  }
74 
75  if (m_avail_memory < length)
76  return false;
77 
78  QueryCacheEntry entry(*key, tablename, row, columns, cell_count,
79  result, result_length);
80 
81  auto insert_result = m_cache.push_back(entry);
82  assert(insert_result.second);
83  (void)insert_result;
84 
85  m_avail_memory -= length;
86 
87  return true;
88 }
89 
90 
91 bool QueryCache::lookup(Key *key, boost::shared_array<uint8_t> &result,
92  uint32_t *lenp, uint32_t *cell_count) {
93  lock_guard<MutexWithStatistics> lock(m_mutex);
94  LookupHashIndex &hash_index = m_cache.get<1>();
95  LookupHashIndex::iterator iter;
96 
97  if (m_total_lookup_count > 0 && (m_total_lookup_count % 1000) == 0) {
98  HT_INFOF("QueryCache hit rate over last 1000 lookups, cumulative = %f, %f",
99  ((double)m_recent_hit_count / (double)1000)*100.0,
100  ((double)m_total_hit_count / (double)m_total_lookup_count)*100.0);
101  m_recent_hit_count = 0;
102  }
103 
105 
106  if ((iter = hash_index.find(*key)) == hash_index.end())
107  return false;
108 
109  QueryCacheEntry entry = *iter;
110 
111  hash_index.erase(iter);
112 
113  pair<Sequence::iterator, bool> insert_result = m_cache.push_back(entry);
114  assert(insert_result.second);
115 
116  result = (*insert_result.first).result;
117  *lenp = (*insert_result.first).result_length;
118  *cell_count = (*insert_result.first).cell_count;
119 
122  return true;
123 }
124 
125 void QueryCache::get_stats(uint64_t *max_memoryp, uint64_t *available_memoryp,
126  uint64_t *total_lookupsp, uint64_t *total_hitsp,
127  int32_t *total_waiters)
128 {
129  lock_guard<MutexWithStatistics> lock(m_mutex);
130  *total_lookupsp = m_total_lookup_count;
131  *total_hitsp = m_total_hit_count;
132  *max_memoryp = m_max_memory;
133  *available_memoryp = m_avail_memory;
134  *total_waiters = m_mutex.get_waiting_threads();
135 }
136 
137 void QueryCache::dump_keys(ofstream &out) {
138  lock_guard<MutexWithStatistics> lock(m_mutex);
139  Sequence &sequence_index = m_cache.get<0>();
140  out << "\nQuery Cache:\n";
141  for (auto &entry : sequence_index) {
142  out << entry.row_key.tablename << "['" << entry.row_key.row << "'] cols={";
143  bool first {true};
144  for (uint8_t cf : entry.columns) {
145  if (!first)
146  out << ",";
147  else
148  first = false;
149  out << (int)cf;
150  }
151  out << "} Length=" << entry.result_length << " CellCount=" << entry.cell_count;
152  if (entry.cell_count > 0) {
153  SerializedKey serkey;
154  serkey.ptr = (uint8_t *)(entry.result.get() + 4);
155  Hypertable::Key key(serkey);
156  out << " FirstKey=(" << key << ")";
157  }
158  out << "\n";
159  }
160 }
161 
162 void QueryCache::invalidate(const char *tablename, const char *row, std::set<uint8_t> &columns) {
163  lock_guard<MutexWithStatistics> lock(m_mutex);
164  InvalidateHashIndex &hash_index = m_cache.get<2>();
165  InvalidateHashIndex::iterator iter;
166  RowKey row_key(tablename, row);
167  pair<InvalidateHashIndex::iterator, InvalidateHashIndex::iterator> p = hash_index.equal_range(row_key);
168  uint64_t length;
169  vector<uint8_t> intersection;
170  bool do_invalidation {};
171 
172  intersection.reserve(columns.size());
173 
174  while (p.first != p.second) {
175  do_invalidation = p.first->columns.empty() || columns.empty();
176  if (!do_invalidation) {
177  intersection.clear();
178  set_intersection(columns.begin(), columns.end(), p.first->columns.begin(),
179  p.first->columns.end(), back_inserter(intersection));
180  do_invalidation = !intersection.empty();
181  }
182  if (do_invalidation) {
183  length = (*p.first).result_length + OVERHEAD + strlen((*p.first).row_key.row);
186  m_avail_memory += length;
187  p.first = hash_index.erase(p.first);
188  }
189  else
190  p.first++;
191  }
192 }
bool lookup(Key *key, boost::shared_array< uint8_t > &result, uint32_t *lenp, uint32_t *cell_count)
Lookup.
Definition: QueryCache.cc:91
void dump_keys(std::ofstream &out)
Dumps keys to output file.
Definition: QueryCache.cc:137
PropertiesPtr properties
This singleton map stores all options.
Definition: Config.cc:47
void invalidate(const char *tablename, const char *row, std::set< uint8_t > &columns)
Invalidates cache entries.
Definition: QueryCache.cc:162
uint64_t m_total_hit_count
Total hit count.
Definition: QueryCache.h:245
void set_statistics_enabled(bool val)
Definition: Mutex.h:47
MutexWithStatistics m_mutex
Mutex to serialize member access
Definition: QueryCache.h:230
STL namespace.
uint64_t m_total_lookup_count
Total lookup count.
Definition: QueryCache.h:242
Internal cache entry.
Definition: QueryCache.h:183
Cache::nth_index< 2 >::type InvalidateHashIndex
Definition: QueryCache.h:227
Hash key to query cache.
Definition: QueryCache.h:54
uint64_t m_max_memory
Maximum memory to be used by cache.
Definition: QueryCache.h:236
QueryCache(uint64_t max_memory)
Constructor.
Definition: QueryCache.cc:40
Cache::nth_index< 0 >::type Sequence
Definition: QueryCache.h:225
Compatibility Macros for C/C++.
void get_stats(uint64_t *max_memoryp, uint64_t *available_memoryp, uint64_t *total_lookupsp, uint64_t *total_hitsp, int32_t *total_waiters)
Gets cache statistics.
Definition: QueryCache.cc:125
const uint8_t * ptr
The pointer to the serialized data.
Definition: ByteString.h:121
Hypertable definitions
#define HT_INFOF(msg,...)
Definition: Logger.h:272
bool insert(Key *key, const char *tablename, const char *row, std::set< uint8_t > &columns, uint32_t cell_count, boost::shared_array< uint8_t > &result, uint32_t result_length)
Inserts a query result.
Definition: QueryCache.cc:47
Provides access to internal components of opaque key.
Definition: Key.h:40
uint64_t m_avail_memory
Available memory.
Definition: QueryCache.h:239
Row key information.
Definition: QueryCache.h:67
#define OVERHEAD
Definition: QueryCache.cc:38
Cache m_cache
Internal cache data structure.
Definition: QueryCache.h:233
Cache::nth_index< 1 >::type LookupHashIndex
Definition: QueryCache.h:226
Configuration settings.
uint32_t m_recent_hit_count
Recent hit count (for logging)
Definition: QueryCache.h:248