@@ -36,13 +36,13 @@ using namespace arangodb::aql;
36
36
37
37
namespace {
38
38
// / @brief singleton instance of the query cache
39
- static arangodb::aql::QueryCache Instance ;
39
+ static arangodb::aql::QueryCache instance ;
40
40
41
41
// / @brief maximum number of results in each per-database cache
42
- static size_t MaxResults = 128 ; // default value. can be changed later
42
+ static std::atomic< size_t > maxResults ( 128 ) ; // default value. can be changed later
43
43
44
44
// / @brief whether or not the cache is enabled
45
- static std::atomic<arangodb::aql::QueryCacheMode> Mode (CACHE_ON_DEMAND);
45
+ static std::atomic<arangodb::aql::QueryCacheMode> mode (CACHE_ON_DEMAND);
46
46
}
47
47
48
48
// / @brief create a cache entry
@@ -55,34 +55,7 @@ QueryCacheResultEntry::QueryCacheResultEntry(
55
55
_queryResult(queryResult),
56
56
_dataSources(dataSources),
57
57
_prev(nullptr ),
58
- _next(nullptr ),
59
- _refCount(0 ),
60
- _deletionRequested(0 ) {
61
- }
62
-
63
- // / @brief check whether the element can be destroyed, and delete it if yes
64
- void QueryCacheResultEntry::tryDelete () {
65
- _deletionRequested = 1 ;
66
-
67
- if (_refCount == 0 ) {
68
- delete this ;
69
- }
70
- }
71
-
72
- // / @brief use the element, so it cannot be deleted meanwhile
73
- void QueryCacheResultEntry::use () { ++_refCount; }
74
-
75
- // / @brief unuse the element, so it can be deleted if required
76
- void QueryCacheResultEntry::unuse () {
77
- TRI_ASSERT (_refCount > 0 );
78
-
79
- if (--_refCount == 0 ) {
80
- if (_deletionRequested == 1 ) {
81
- // trigger the deletion
82
- delete this ;
83
- }
84
- }
85
- }
58
+ _next(nullptr ) {}
86
59
87
60
// / @brief create a database-specific cache
88
61
QueryCacheDatabaseEntry::QueryCacheDatabaseEntry ()
@@ -96,16 +69,12 @@ QueryCacheDatabaseEntry::QueryCacheDatabaseEntry()
96
69
97
70
// / @brief destroy a database-specific cache
98
71
QueryCacheDatabaseEntry::~QueryCacheDatabaseEntry () {
99
- for (auto & it : _entriesByHash) {
100
- tryDelete (it.second );
101
- }
102
-
103
72
_entriesByHash.clear ();
104
73
_entriesByDataSource.clear ();
105
74
}
106
75
107
76
// / @brief lookup a query result in the database-specific cache
108
- QueryCacheResultEntry* QueryCacheDatabaseEntry::lookup (
77
+ std::shared_ptr< QueryCacheResultEntry> QueryCacheDatabaseEntry::lookup (
109
78
uint64_t hash, QueryString const & queryString) {
110
79
auto it = _entriesByHash.find (hash);
111
80
@@ -124,26 +93,20 @@ QueryCacheResultEntry* QueryCacheDatabaseEntry::lookup(
124
93
}
125
94
126
95
// found an entry
127
- auto entry = (*it).second ;
128
-
129
- // mark the entry as being used so noone else can delete it while it is in use
130
- entry->use ();
131
-
132
- return entry;
96
+ return (*it).second ;
133
97
}
134
98
135
99
// / @brief store a query result in the database-specific cache
136
100
void QueryCacheDatabaseEntry::store (uint64_t hash,
137
- QueryCacheResultEntry* entry) {
101
+ std::shared_ptr< QueryCacheResultEntry> entry) {
138
102
// insert entry into the cache
139
103
if (!_entriesByHash.emplace (hash, entry).second ) {
140
104
// remove previous entry
141
105
auto it = _entriesByHash.find (hash);
142
106
TRI_ASSERT (it != _entriesByHash.end ());
143
107
auto previous = (*it).second ;
144
- unlink (previous);
108
+ unlink (previous. get () );
145
109
_entriesByHash.erase (it);
146
- tryDelete (previous);
147
110
148
111
// and insert again
149
112
_entriesByHash.emplace (hash, entry);
@@ -178,19 +141,19 @@ void QueryCacheDatabaseEntry::store(uint64_t hash,
178
141
TRI_ASSERT (it != _entriesByHash.end ());
179
142
auto previous = (*it).second ;
180
143
_entriesByHash.erase (it);
181
- unlink (previous);
182
- tryDelete (previous);
144
+ unlink (previous.get ());
183
145
throw ;
184
146
}
185
147
186
- link (entry);
148
+ link (entry. get () );
187
149
188
- enforceMaxResults (::MaxResults);
150
+ size_t mr = ::maxResults.load ();
151
+ enforceMaxResults (mr);
189
152
190
- TRI_ASSERT (_numElements <= ::MaxResults );
153
+ TRI_ASSERT (_numElements <= mr );
191
154
TRI_ASSERT (_head != nullptr );
192
155
TRI_ASSERT (_tail != nullptr );
193
- TRI_ASSERT (_tail == entry);
156
+ TRI_ASSERT (_tail == entry. get () );
194
157
TRI_ASSERT (entry->_next == nullptr );
195
158
}
196
159
@@ -218,20 +181,18 @@ void QueryCacheDatabaseEntry::invalidate(std::string const& dataSource) {
218
181
if (it3 != _entriesByHash.end ()) {
219
182
// remove entry from the linked list
220
183
auto entry = (*it3).second ;
221
- unlink (entry);
184
+ unlink (entry. get () );
222
185
223
186
// erase it from hash table
224
187
_entriesByHash.erase (it3);
225
-
226
- // delete the object itself
227
- tryDelete (entry);
228
188
}
229 189
}
230
190
231
191
_entriesByDataSource.erase (it);
232
192
}
233
193
234
194
// / @brief enforce maximum number of results
195
+ // / must be called under the shard's lock
235
196
void QueryCacheDatabaseEntry::enforceMaxResults (size_t value) {
236
197
while (_numElements > value) {
237
198
// too many elements. now wipe the first element from the list
@@ -242,15 +203,9 @@ void QueryCacheDatabaseEntry::enforceMaxResults(size_t value) {
242
203
auto it = _entriesByHash.find (head->_hash );
243
204
TRI_ASSERT (it != _entriesByHash.end ());
244
205
_entriesByHash.erase (it);
245
- tryDelete (head);
246
206
}
247
207
}
248
208
249
- // / @brief check whether the element can be destroyed, and delete it if yes
250
- void QueryCacheDatabaseEntry::tryDelete (QueryCacheResultEntry* e) {
251
- e->tryDelete ();
252
- }
253
-
254
209
// / @brief unlink the result entry from the list
255
210
void QueryCacheDatabaseEntry::unlink (QueryCacheResultEntry* e) {
256
211
if (e->_prev != nullptr ) {
@@ -313,7 +268,7 @@ VPackBuilder QueryCache::properties() {
313
268
VPackBuilder builder;
314
269
builder.openObject ();
315
270
builder.add (" mode" , VPackValue (modeString (mode ())));
316
- builder.add (" maxResults" , VPackValue (::MaxResults ));
271
+ builder.add (" maxResults" , VPackValue (::maxResults. load () ));
317
272
builder.close ();
318
273
319
274
return builder;
@@ -324,7 +279,7 @@ void QueryCache::properties(std::pair<std::string, size_t>& result) {
324
279
MUTEX_LOCKER (mutexLocker, _propertiesLock);
325
280
326
281
result.first = modeString (mode ());
327
- result.second = ::MaxResults ;
282
+ result.second = ::maxResults. load () ;
328
283
}
329
284
330
285
// / @brief set the cache properties
@@ -343,7 +298,7 @@ bool QueryCache::mayBeActive() const { return (mode() != CACHE_ALWAYS_OFF); }
343
298
344
299
// / @brief return whether or not the query cache is enabled
345
300
QueryCacheMode QueryCache::mode () const {
346
- return ::Mode .load (std::memory_order_relaxed);
301
+ return ::mode .load (std::memory_order_relaxed);
347
302
}
348
303
349
304
// / @brief return a string version of the mode
@@ -362,8 +317,8 @@ std::string QueryCache::modeString(QueryCacheMode mode) {
362
317
}
363
318
364
319
// / @brief lookup a query result in the cache
365
- QueryCacheResultEntry* QueryCache::lookup (TRI_vocbase_t* vocbase, uint64_t hash,
366
- QueryString const & queryString) {
320
+ std::shared_ptr< QueryCacheResultEntry> QueryCache::lookup (TRI_vocbase_t* vocbase, uint64_t hash,
321
+ QueryString const & queryString) {
367
322
auto const part = getPart (vocbase);
368
323
READ_LOCKER (readLocker, _entriesLock[part]);
369
324
@@ -380,21 +335,21 @@ QueryCacheResultEntry* QueryCache::lookup(TRI_vocbase_t* vocbase, uint64_t hash,
380
335
// / @brief store a query in the cache
381
336
// / if the call is successful, the cache has taken over ownership for the
382
337
// / query result!
383
- QueryCacheResultEntry* QueryCache::store (
338
+ void QueryCache::store (
384
339
TRI_vocbase_t* vocbase, uint64_t hash, QueryString const & queryString,
385
340
std::shared_ptr<VPackBuilder> const & result,
386
341
std::shared_ptr<VPackBuilder> const & stats,
387
342
std::vector<std::string>&& dataSources) {
388
343
389
344
if (!result->slice ().isArray ()) {
390
- return nullptr ;
345
+ return ;
391
346
}
392
347
393
348
// get the right part of the cache to store the result in
394
349
auto const part = getPart (vocbase);
395
350
396
351
// create the cache entry outside the lock
397
- auto entry = std::make_unique <QueryCacheResultEntry>(
352
+ auto entry = std::make_shared <QueryCacheResultEntry>(
398
353
hash, queryString, result, std::move (dataSources));
399
354
400
355
WRITE_LOCKER (writeLocker, _entriesLock[part]);
@@ -404,17 +359,15 @@ QueryCacheResultEntry* QueryCache::store(
404
359
if (it == _entries[part].end ()) {
405
360
// create entry for the current database
406
361
auto db = std::make_unique<QueryCacheDatabaseEntry>();
407
- it = _entries[part].emplace (vocbase, db.get ()).first ;
408
- db.release ();
362
+ it = _entries[part].emplace (vocbase, std::move (db)).first ;
409
363
}
410
364
411
365
// store cache entry
412
- (*it).second ->store (hash, entry.get ());
413
- return entry.release ();
366
+ (*it).second ->store (hash, entry);
414
367
}
415
368
416
369
// / @brief store a query in the cache
417
- void QueryCache::store (TRI_vocbase_t* vocbase, std::unique_ptr <QueryCacheResultEntry> entry) {
370
+ void QueryCache::store (TRI_vocbase_t* vocbase, std::shared_ptr <QueryCacheResultEntry> entry) {
418
371
// get the right part of the cache to store the result in
419
372
auto const part = getPart (vocbase);
420
373
@@ -425,13 +378,11 @@ void QueryCache::store(TRI_vocbase_t* vocbase, std::unique_ptr<QueryCacheResultE
425
378
if (it == _entries[part].end ()) {
426
379
// create entry for the current database
427
380
auto db = std::make_unique<QueryCacheDatabaseEntry>();
428
- it = _entries[part].emplace (vocbase, db.get ()).first ;
429
- db.release ();
381
+ it = _entries[part].emplace (vocbase, std::move (db)).first ;
430
382
}
431
383
432
384
// store cache entry
433
- (*it).second ->store (entry->_hash , entry.get ());
434
- entry.release ();
385
+ (*it).second ->store (entry->_hash , entry);
435
386
}
436
387
437
388
// / @brief invalidate all queries for the given data sources
@@ -467,7 +418,7 @@ void QueryCache::invalidate(TRI_vocbase_t* vocbase, std::string const& dataSourc
467
418
468
419
// / @brief invalidate all queries for a particular database
469
420
void QueryCache::invalidate (TRI_vocbase_t* vocbase) {
470
- QueryCacheDatabaseEntry* databaseQueryCache = nullptr ;
421
+ std::unique_ptr< QueryCacheDatabaseEntry> databaseQueryCache;
471
422
472
423
{
473
424
auto const part = getPart (vocbase);
@@ -479,13 +430,12 @@ void QueryCache::invalidate(TRI_vocbase_t* vocbase) {
479
430
return ;
480
431
}
481
432
482
- databaseQueryCache = ( *it).second ;
433
+ databaseQueryCache = std::move (( *it).second ) ;
483
434
_entries[part].erase (it);
484
435
}
485
436
486
437
// delete without holding the lock
487
438
TRI_ASSERT (databaseQueryCache != nullptr );
488
- delete databaseQueryCache;
489
439
}
490
440
491
441
// / @brief invalidate all queries
@@ -504,7 +454,7 @@ void QueryCache::invalidate() {
504
454
}
505
455
506
456
// / @brief get the query cache instance
507
- QueryCache* QueryCache::instance () { return &::Instance ; }
457
+ QueryCache* QueryCache::instance () { return &::instance ; }
508
458
509
459
// / @brief enforce maximum number of elements in each database-specific cache
510
460
void QueryCache::enforceMaxResults (size_t value) {
@@ -527,10 +477,6 @@ unsigned int QueryCache::getPart(TRI_vocbase_t const* vocbase) const {
527
477
// / @brief invalidate all entries in the cache part
528
478
// / note that the caller of this method must hold the write lock
529
479
void QueryCache::invalidate (unsigned int part) {
530
- for (auto & it : _entries[part]) {
531
- delete it.second ;
532
- }
533
-
534
480
_entries[part].clear ();
535
481
}
536
482
@@ -540,11 +486,13 @@ void QueryCache::setMaxResults(size_t value) {
540
486
return ;
541
487
}
542
488
543
- if (value > ::MaxResults) {
489
+ size_t mr = ::maxResults.load ();
490
+
491
+ if (value > mr) {
544
492
enforceMaxResults (value);
545
493
}
546
494
547
- ::MaxResults = value;
495
+ mr = value;
548
496
}
549
497
550
498
// / @brief sets the caching mode
@@ -556,7 +504,7 @@ void QueryCache::setMode(QueryCacheMode value) {
556
504
557
505
invalidate ();
558
506
559
- ::Mode .store (value, std::memory_order_release);
507
+ ::mode .store (value, std::memory_order_release);
560
508
}
561
509
562
510
// / @brief enable or disable the query cache
0 commit comments