CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sqlitemem.cc
Go to the documentation of this file.
1 
5 #define __STDC_FORMAT_MACROS
6 
7 
8 #include "sqlitemem.h"
9 
10 #include <cassert>
11 #include <cstddef>
12 #include <cstring>
13 #include <new>
14 
15 #include "malloc_arena.h"
16 #include "util/concurrency.h"
17 #include "util/exception.h"
18 #include "util/smalloc.h"
19 
20 using namespace std; // NOLINT
21 
22 
24  for (unsigned i = 0; i < kNoBitmaps; ++i) {
25  int bit_set = ffs(freemap_[i]);
26  if (bit_set != 0) {
27  freemap_[i] &= ~(1 << (bit_set - 1)); // set bit to zero
28  const int nbuffer = i * sizeof(int) * 8 + bit_set - 1;
29  return reinterpret_cast<char *>(arena_) + nbuffer * kBufferSize;
30  }
31  }
32  return NULL;
33 }
34 
35 
37  for (unsigned i = 0; i < kNoBitmaps; ++i) {
38  if (~freemap_[i] != 0)
39  return false;
40  }
41  return true;
42 }
43 
44 
46  if ((buffer == NULL) || (buffer < arena_))
47  return false;
48  return (static_cast<uint64_t>((reinterpret_cast<char *>(buffer)
49  - reinterpret_cast<char *>(arena_)))
50  < kArenaSize);
51 }
52 
53 
55  : arena_(sxmmap(kArenaSize)) {
56  // All buffers unused, i.e. all bits set
57  memset(freemap_, 0xFF, kNoBitmaps * sizeof(int));
58 }
59 
60 
62  sxunmap(arena_, kArenaSize);
63 }
64 
65 
67  assert(buffer >= arena_);
68  ptrdiff_t nbuffer = (reinterpret_cast<char *>(buffer)
69  - reinterpret_cast<char *>(arena_))
70  / kBufferSize;
71  assert(static_cast<uint64_t>(nbuffer) < kBuffersPerArena);
72  const int nfreemap = nbuffer / (sizeof(int) * 8);
73  freemap_[nfreemap] |= 1 << (nbuffer % (sizeof(int) * 8));
74 }
75 
76 
77 //------------------------------------------------------------------------------
78 
79 
81 
82 
87  return instance_->GetMemory(size);
88 }
89 
90 
95 
96 
100 void *SqliteMemoryManager::xRealloc(void *ptr, int new_size) {
101  int old_size = xSize(ptr);
102  if (old_size >= new_size)
103  return ptr;
104 
105  void *new_ptr = xMalloc(new_size);
106  memcpy(new_ptr, ptr, old_size);
107  xFree(ptr);
108  return new_ptr;
109 }
110 
111 
116  return instance_->GetMemorySize(ptr);
117 }
118 
119 
120 int SqliteMemoryManager::xRoundup(int size) { return RoundUp8(size); }
121 
122 
123 int SqliteMemoryManager::xInit(void *app_data __attribute__((unused))) {
124  return SQLITE_OK;
125 }
126 
127 
128 void SqliteMemoryManager::xShutdown(void *app_data __attribute__((unused))) { }
129 
130 
132  if (assigned_)
133  return;
134  int retval;
135 
136  retval = sqlite3_config(SQLITE_CONFIG_PAGECACHE, page_cache_memory_,
138  assert(retval == SQLITE_OK);
139 
140  retval = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &sqlite3_mem_vanilla_);
141  assert(retval == SQLITE_OK);
142  retval = sqlite3_config(SQLITE_CONFIG_MALLOC, &mem_methods_);
143  assert(retval == SQLITE_OK);
144 
145  assigned_ = true;
146 }
147 
148 
154  MutexLockGuard lock_guard(lock_);
155 
156  void *buffer = GetLookasideBuffer();
157  assert(buffer != NULL);
158  int retval = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, buffer,
160  assert(retval == SQLITE_OK);
161  return buffer;
162 }
163 
164 
166  delete instance_;
167  instance_ = NULL;
168 }
169 
170 
175  void *result;
176  vector<LookasideBufferArena *>::reverse_iterator
177  reverse_iter = lookaside_buffer_arenas_.rbegin();
178  vector<LookasideBufferArena *>::reverse_iterator
179  i_rend = lookaside_buffer_arenas_.rend();
180  for (; reverse_iter != i_rend; ++reverse_iter) {
181  result = (*reverse_iter)->GetBuffer();
182  if (result != NULL)
183  return result;
184  }
185 
186  LookasideBufferArena *new_arena = new LookasideBufferArena();
187  lookaside_buffer_arenas_.push_back(new_arena);
188  return new_arena->GetBuffer();
189 }
190 
191 
194 }
195 
196 
201  void *p = malloc_arenas_[idx_last_arena_]->Malloc(size);
202  if (p != NULL)
203  return p;
204  unsigned N = malloc_arenas_.size();
205  for (unsigned i = 0; i < N; ++i) {
206  p = malloc_arenas_[i]->Malloc(size);
207  if (p != NULL) {
208  idx_last_arena_ = i;
209  return p;
210  }
211  }
212  idx_last_arena_ = N;
214  malloc_arenas_.push_back(M);
215  p = M->Malloc(size);
216  assert(p != NULL);
217  return p;
218 }
219 
220 
222  : assigned_(false)
224  , idx_last_arena_(0) {
225  memset(&sqlite3_mem_vanilla_, 0, sizeof(sqlite3_mem_vanilla_));
226  int retval = pthread_mutex_init(&lock_, NULL);
227  assert(retval == 0);
228 
230  malloc_arenas_.push_back(new MallocArena(kArenaSize));
231 
232  memset(&mem_methods_, 0, sizeof(mem_methods_));
233  mem_methods_.xMalloc = xMalloc;
234  mem_methods_.xFree = xFree;
235  mem_methods_.xRealloc = xRealloc;
236  mem_methods_.xSize = xSize;
237  mem_methods_.xRoundup = xRoundup;
238  mem_methods_.xInit = xInit;
239  mem_methods_.xShutdown = xShutdown;
240  mem_methods_.pAppData = NULL;
241 }
242 
243 
248  if (assigned_) {
249  // Reset sqlite to default values
250  int retval;
251  retval = sqlite3_config(SQLITE_CONFIG_PAGECACHE, NULL, 0, 0);
252  assert(retval == SQLITE_OK);
253  retval = sqlite3_config(SQLITE_CONFIG_MALLOC, &sqlite3_mem_vanilla_);
254  assert(retval == SQLITE_OK);
255  }
256 
258  for (unsigned i = 0; i < lookaside_buffer_arenas_.size(); ++i)
259  delete lookaside_buffer_arenas_[i];
260  for (unsigned i = 0; i < malloc_arenas_.size(); ++i)
261  delete malloc_arenas_[i];
262  pthread_mutex_destroy(&lock_);
263 }
264 
265 
272  unsigned N = lookaside_buffer_arenas_.size();
273  for (unsigned i = 0; i < N; ++i) {
274  if (lookaside_buffer_arenas_[i]->Contains(buffer)) {
275  lookaside_buffer_arenas_[i]->PutBuffer(buffer);
276  if ((N > 1) && lookaside_buffer_arenas_[i]->IsEmpty()) {
277  delete lookaside_buffer_arenas_[i];
279  }
280  return;
281  }
282  }
283  PANIC(NULL);
284 }
285 
286 
292  M->Free(ptr);
293  unsigned N = malloc_arenas_.size();
294  if ((N > 1) && M->IsEmpty()) {
295  for (unsigned i = 0; i < N; ++i) {
296  if (malloc_arenas_[i] == M) {
297  delete malloc_arenas_[i];
298  malloc_arenas_.erase(malloc_arenas_.begin() + i);
299  idx_last_arena_ = 0;
300  return;
301  }
302  }
303  PANIC(NULL);
304  }
305 }
306 
307 
312  MutexLockGuard lock_guard(lock_);
313  PutLookasideBuffer(buffer);
314 }
struct sqlite3_mem_methods sqlite3_mem_vanilla_
Definition: sqlitemem.h:194
static const unsigned kPageCacheSlotSize
Definition: sqlitemem.h:65
static MallocArena * GetMallocArena(void *ptr, unsigned arena_size)
Definition: malloc_arena.h:77
static const unsigned kPageCacheNoSlots
Definition: sqlitemem.h:69
struct sqlite3_mem_methods mem_methods_
Definition: sqlitemem.h:196
const unsigned kBufferSize
Definition: compression.cc:148
static int xInit(void *app_data)
Definition: sqlitemem.cc:123
#define PANIC(...)
Definition: exception.h:29
static int xSize(void *ptr)
Definition: sqlitemem.cc:115
static const unsigned kArenaSize
Definition: sqlitemem.h:157
void * GetLookasideBuffer()
Definition: sqlitemem.cc:174
static void xShutdown(void *app_data)
Definition: sqlitemem.cc:128
assert((mem||(size==0))&&"Out Of Memory")
void PutMemory(void *ptr)
Definition: sqlitemem.cc:290
static void CleanupInstance()
Definition: sqlitemem.cc:165
void AssignGlobalArenas()
Definition: sqlitemem.cc:131
struct cvmcache_object_info __attribute__
Definition: atomic.h:24
int GetMemorySize(void *ptr)
Definition: sqlitemem.cc:192
static const unsigned kLookasideSlotsPerDb
Definition: sqlitemem.h:83
void * GetMemory(int size)
Definition: sqlitemem.cc:200
static const unsigned kPageCacheSize
Definition: sqlitemem.h:73
static SqliteMemoryManager * instance_
Definition: sqlitemem.h:158
static void * xRealloc(void *ptr, int new_size)
Definition: sqlitemem.cc:100
static uint64_t RoundUp8(const uint64_t size)
Definition: smalloc.h:37
unsigned idx_last_arena_
Definition: sqlitemem.h:203
void Free(void *ptr)
Definition: malloc_arena.cc:54
static void xFree(void *ptr)
Definition: sqlitemem.cc:94
pthread_mutex_t lock_
Definition: sqlitemem.h:182
void * page_cache_memory_
Definition: sqlitemem.h:197
static const unsigned kLookasideSlotSize
Definition: sqlitemem.h:79
bool IsEmpty() const
Definition: malloc_arena.h:95
static int xRoundup(int size)
Definition: sqlitemem.cc:120
void * Malloc(const uint32_t size)
Definition: mutex.h:42
void PutLookasideBuffer(void *buffer)
Definition: sqlitemem.cc:271
uint32_t GetSize(void *ptr) const
std::vector< LookasideBufferArena * > lookaside_buffer_arenas_
Definition: sqlitemem.h:198
static void size_t size
Definition: smalloc.h:54
static void * xMalloc(int size)
Definition: sqlitemem.cc:86
void ReleaseLookasideBuffer(void *buffer)
Definition: sqlitemem.cc:311
void * AssignLookasideBuffer(sqlite3 *db)
Definition: sqlitemem.cc:153
std::vector< MallocArena * > malloc_arenas_
Definition: sqlitemem.h:199