0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
FileBlockCache.cc
Go to the documentation of this file.
1 /* -*- c++ -*-
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 
24 #include "FileBlockCache.h"
25 
26 #include <cassert>
27 #include <iostream>
28 #include <utility>
29 
30 using namespace Hypertable;
31 using namespace std;
32 
33 atomic<int> FileBlockCache::ms_next_file_id {0};
34 
36  lock_guard<mutex> lock(m_mutex);
37  for (BlockCache::const_iterator iter = m_cache.begin();
38  iter != m_cache.end(); ++iter)
39  if (!iter->event)
40  delete [] (*iter).block;
41  m_cache.clear();
42 }
43 
44 bool
45 FileBlockCache::checkout(int file_id, uint64_t file_offset, uint8_t **blockp,
46  uint32_t *lengthp) {
47  lock_guard<mutex> lock(m_mutex);
48  HashIndex &hash_index = m_cache.get<1>();
49  HashIndex::iterator iter;
50 
51  m_accesses++;
52 
53  if ((iter = hash_index.find(make_key(file_id, file_offset))) == hash_index.end())
54  return false;
55 
56  BlockCacheEntry entry = *iter;
57  entry.ref_count++;
58 
59  hash_index.erase(iter);
60 
61  pair<Sequence::iterator, bool> insert_result = m_cache.push_back(entry);
62  assert(insert_result.second);
63 
64  *blockp = (*insert_result.first).block;
65  *lengthp = (*insert_result.first).length;
66 
67  m_hits++;
68  return true;
69 }
70 
71 
72 void FileBlockCache::checkin(int file_id, uint64_t file_offset) {
73  lock_guard<mutex> lock(m_mutex);
74  HashIndex &hash_index = m_cache.get<1>();
75  HashIndex::iterator iter;
76 
77  iter = hash_index.find(make_key(file_id, file_offset));
78 
79  assert(iter != hash_index.end() && (*iter).ref_count > 0);
80 
81  hash_index.modify(iter, DecrementRefCount());
82 }
83 
84 
85 bool
86 FileBlockCache::insert(int file_id, uint64_t file_offset,
87  uint8_t *block, uint32_t length,
88  const EventPtr &event, bool checkout) {
89  lock_guard<mutex> lock(m_mutex);
90  HashIndex &hash_index = m_cache.get<1>();
91 
92  if (hash_index.find(make_key(file_id, file_offset)) != hash_index.end())
93  return false;
94 
95  if (m_available < length)
96  make_room(length);
97 
98  if (m_available < length) {
99  if ((length-m_available) <= (m_max_memory-m_limit)) {
100  m_limit += (length-m_available);
101  m_available += (length-m_available);
102  }
103  else
104  return false;
105  }
106 
107  BlockCacheEntry entry(file_id, file_offset, event);
108  entry.block = block;
109  entry.length = length;
110  entry.ref_count = checkout ? 1 : 0;
111 
112  pair<Sequence::iterator, bool> insert_result = m_cache.push_back(entry);
113  assert(insert_result.second);
114  (void)insert_result;
115 
116  m_available -= length;
117 
118  return true;
119 }
120 
121 
122 bool FileBlockCache::contains(int file_id, uint64_t file_offset) {
123  lock_guard<mutex> lock(m_mutex);
124  HashIndex &hash_index = m_cache.get<1>();
125  m_accesses++;
126 
127  if (hash_index.find(make_key(file_id, file_offset)) != hash_index.end()) {
128  m_hits++;
129  return true;
130  }
131  else
132  return false;
133 }
134 
135 
136 void FileBlockCache::increase_limit(int64_t amount) {
137  lock_guard<mutex> lock(m_mutex);
138  int64_t adjusted_amount = amount;
139  if ((m_max_memory-m_limit) < amount)
140  adjusted_amount = m_max_memory - m_limit;
141  m_limit += adjusted_amount;
142  m_available += adjusted_amount;
143 }
144 
145 
146 int64_t FileBlockCache::decrease_limit(int64_t amount) {
147  lock_guard<mutex> lock(m_mutex);
148  int64_t memory_freed = 0;
149  if (m_available < amount) {
150  if (amount > (m_limit - m_min_memory))
151  amount = m_limit - m_min_memory;
152  memory_freed = make_room(amount);
153  if (m_available < amount)
154  amount = m_available;
155  }
156  m_available -= amount;
157  m_limit -= amount;
158  return memory_freed;
159 }
160 
161 
162 int64_t FileBlockCache::make_room(int64_t amount) {
163  BlockCache::iterator iter = m_cache.begin();
164  int64_t amount_freed = 0;
165  while (iter != m_cache.end()) {
166  if ((*iter).ref_count == 0) {
167  m_available += (*iter).length;
168  amount_freed += (*iter).length;
169  if (!iter->event)
170  delete [] iter->block;
171  iter = m_cache.erase(iter);
172  if (m_available >= amount)
173  break;
174  }
175  else
176  ++iter;
177  }
178  return amount_freed;
179 }
180 
181 void FileBlockCache::get_stats(uint64_t *max_memoryp, uint64_t *available_memoryp,
182  uint64_t *accessesp, uint64_t *hitsp) {
183  lock_guard<mutex> lock(m_mutex);
184  *max_memoryp = m_limit;
185  *available_memoryp = m_available;
186  *accessesp = m_accesses;
187  *hitsp = m_hits;
188 }
int64_t make_room(int64_t amount)
static std::atomic< int > ms_next_file_id
uint32_t length
std::shared_ptr< Event > EventPtr
Smart pointer to Event.
Definition: Event.h:228
STL namespace.
bool contains(int file_id, uint64_t file_offset)
uint32_t ref_count
void checkin(int file_id, uint64_t file_offset)
Compatibility Macros for C/C++.
uint8_t * block
void increase_limit(int64_t amount)
bool insert(int file_id, uint64_t file_offset, uint8_t *block, uint32_t length, const EventPtr &event, bool checkout)
Hypertable definitions
bool checkout(int file_id, uint64_t file_offset, uint8_t **blockp, uint32_t *lengthp)
void get_stats(uint64_t *max_memoryp, uint64_t *available_memoryp, uint64_t *accessesp, uint64_t *hitsp)
int64_t decrease_limit(int64_t amount)
Lowers the memory limit.
BlockCache::nth_index< 1 >::type HashIndex