CernVM-FS  2.12.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 #include "cvmfs_config.h"
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>(
49  (reinterpret_cast<char *>(buffer) - reinterpret_cast<char *>(arena_))) <
50  kArenaSize);
51 }
52 
53 
55  : arena_(sxmmap(kArenaSize))
56 {
57  // All buffers unused, i.e. all bits set
58  memset(freemap_, 0xFF, kNoBitmaps * sizeof(int));
59 }
60 
61 
63  sxunmap(arena_, kArenaSize);
64 }
65 
66 
68  assert(buffer >= arena_);
69  ptrdiff_t nbuffer =
70  (reinterpret_cast<char *>(buffer) - reinterpret_cast<char *>(arena_))
71  / kBufferSize;
72  assert(static_cast<uint64_t>(nbuffer) < kBuffersPerArena);
73  const int nfreemap = nbuffer / (sizeof(int) * 8);
74  freemap_[nfreemap] |= 1 << (nbuffer % (sizeof(int) * 8));
75 }
76 
77 
78 //------------------------------------------------------------------------------
79 
80 
82 
83 
88  return instance_->GetMemory(size);
89 }
90 
91 
95 void SqliteMemoryManager::xFree(void *ptr) {
96  instance_->PutMemory(ptr);
97 }
98 
99 
103 void *SqliteMemoryManager::xRealloc(void *ptr, int new_size) {
104  int old_size = xSize(ptr);
105  if (old_size >= new_size)
106  return ptr;
107 
108  void *new_ptr = xMalloc(new_size);
109  memcpy(new_ptr, ptr, old_size);
110  xFree(ptr);
111  return new_ptr;
112 }
113 
114 
119  return instance_->GetMemorySize(ptr);
120 }
121 
122 
124  return RoundUp8(size);
125 }
126 
127 
128 int SqliteMemoryManager::xInit(void *app_data __attribute__((unused))) {
129  return SQLITE_OK;
130 }
131 
132 
133 void SqliteMemoryManager::xShutdown(void *app_data __attribute__((unused))) {
134 }
135 
136 
138  if (assigned_) return;
139  int retval;
140 
141  retval = sqlite3_config(SQLITE_CONFIG_PAGECACHE, page_cache_memory_,
143  assert(retval == SQLITE_OK);
144 
145  retval = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &sqlite3_mem_vanilla_);
146  assert(retval == SQLITE_OK);
147  retval = sqlite3_config(SQLITE_CONFIG_MALLOC, &mem_methods_);
148  assert(retval == SQLITE_OK);
149 
150  assigned_ = true;
151 }
152 
153 
159  MutexLockGuard lock_guard(lock_);
160 
161  void *buffer = GetLookasideBuffer();
162  assert(buffer != NULL);
163  int retval = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,
165  assert(retval == SQLITE_OK);
166  return buffer;
167 }
168 
169 
171  delete instance_;
172  instance_ = NULL;
173 }
174 
175 
180  void *result;
181  vector<LookasideBufferArena *>::reverse_iterator reverse_iter =
182  lookaside_buffer_arenas_.rbegin();
183  vector<LookasideBufferArena *>::reverse_iterator i_rend =
185  for (; reverse_iter != i_rend; ++reverse_iter) {
186  result = (*reverse_iter)->GetBuffer();
187  if (result != NULL)
188  return result;
189  }
190 
191  LookasideBufferArena *new_arena = new LookasideBufferArena();
192  lookaside_buffer_arenas_.push_back(new_arena);
193  return new_arena->GetBuffer();
194 }
195 
196 
199 }
200 
201 
206  void *p = malloc_arenas_[idx_last_arena_]->Malloc(size);
207  if (p != NULL)
208  return p;
209  unsigned N = malloc_arenas_.size();
210  for (unsigned i = 0; i < N; ++i) {
211  p = malloc_arenas_[i]->Malloc(size);
212  if (p != NULL) {
213  idx_last_arena_ = i;
214  return p;
215  }
216  }
217  idx_last_arena_ = N;
219  malloc_arenas_.push_back(M);
220  p = M->Malloc(size);
221  assert(p != NULL);
222  return p;
223 }
224 
225 
227  : assigned_(false)
229  , idx_last_arena_(0)
230 {
231  memset(&sqlite3_mem_vanilla_, 0, sizeof(sqlite3_mem_vanilla_));
232  int retval = pthread_mutex_init(&lock_, NULL);
233  assert(retval == 0);
234 
236  malloc_arenas_.push_back(new MallocArena(kArenaSize));
237 
238  memset(&mem_methods_, 0, sizeof(mem_methods_));
239  mem_methods_.xMalloc = xMalloc;
240  mem_methods_.xFree = xFree;
241  mem_methods_.xRealloc = xRealloc;
242  mem_methods_.xSize = xSize;
243  mem_methods_.xRoundup = xRoundup;
244  mem_methods_.xInit = xInit;
245  mem_methods_.xShutdown = xShutdown;
246  mem_methods_.pAppData = NULL;
247 }
248 
249 
254  if (assigned_) {
255  // Reset sqlite to default values
256  int retval;
257  retval = sqlite3_config(SQLITE_CONFIG_PAGECACHE, NULL, 0, 0);
258  assert(retval == SQLITE_OK);
259  retval = sqlite3_config(SQLITE_CONFIG_MALLOC, &sqlite3_mem_vanilla_);
260  assert(retval == SQLITE_OK);
261  }
262 
264  for (unsigned i = 0; i < lookaside_buffer_arenas_.size(); ++i)
265  delete lookaside_buffer_arenas_[i];
266  for (unsigned i = 0; i < malloc_arenas_.size(); ++i)
267  delete malloc_arenas_[i];
268  pthread_mutex_destroy(&lock_);
269 }
270 
271 
278  unsigned N = lookaside_buffer_arenas_.size();
279  for (unsigned i = 0; i < N; ++i) {
280  if (lookaside_buffer_arenas_[i]->Contains(buffer)) {
281  lookaside_buffer_arenas_[i]->PutBuffer(buffer);
282  if ((N > 1) && lookaside_buffer_arenas_[i]->IsEmpty()) {
283  delete lookaside_buffer_arenas_[i];
285  }
286  return;
287  }
288  }
289  PANIC(NULL);
290 }
291 
292 
298  M->Free(ptr);
299  unsigned N = malloc_arenas_.size();
300  if ((N > 1) && M->IsEmpty()) {
301  for (unsigned i = 0; i < N; ++i) {
302  if (malloc_arenas_[i] == M) {
303  delete malloc_arenas_[i];
304  malloc_arenas_.erase(malloc_arenas_.begin() + i);
305  idx_last_arena_ = 0;
306  return;
307  }
308  }
309  PANIC(NULL);
310  }
311 }
312 
313 
318  MutexLockGuard lock_guard(lock_);
319  PutLookasideBuffer(buffer);
320 }
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:143
static int xInit(void *app_data)
Definition: sqlitemem.cc:128
#define PANIC(...)
Definition: exception.h:29
static int xSize(void *ptr)
Definition: sqlitemem.cc:118
static const unsigned kArenaSize
Definition: sqlitemem.h:157
void * GetLookasideBuffer()
Definition: sqlitemem.cc:179
static void xShutdown(void *app_data)
Definition: sqlitemem.cc:133
assert((mem||(size==0))&&"Out Of Memory")
void PutMemory(void *ptr)
Definition: sqlitemem.cc:296
static void CleanupInstance()
Definition: sqlitemem.cc:170
void AssignGlobalArenas()
Definition: sqlitemem.cc:137
struct cvmcache_object_info __attribute__
Definition: atomic.h:24
int GetMemorySize(void *ptr)
Definition: sqlitemem.cc:197
static const unsigned kLookasideSlotsPerDb
Definition: sqlitemem.h:83
void * GetMemory(int size)
Definition: sqlitemem.cc:205
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:103
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:55
static void xFree(void *ptr)
Definition: sqlitemem.cc:95
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:123
void * Malloc(const uint32_t size)
Definition: mutex.h:42
void PutLookasideBuffer(void *buffer)
Definition: sqlitemem.cc:277
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:87
void ReleaseLookasideBuffer(void *buffer)
Definition: sqlitemem.cc:317
void * AssignLookasideBuffer(sqlite3 *db)
Definition: sqlitemem.cc:158
std::vector< MallocArena * > malloc_arenas_
Definition: sqlitemem.h:199