1#pragma once
2
3#include <memory>
4
5#include <Common/LRUCache.h>
6#include <Common/ProfileEvents.h>
7#include <Common/SipHash.h>
8#include <Interpreters/AggregationCommon.h>
9#include <DataStreams/MarkInCompressedFile.h>
10
11
12namespace ProfileEvents
13{
14 extern const Event MarkCacheHits;
15 extern const Event MarkCacheMisses;
16}
17
18namespace DB
19{
20
21/// Estimate of number of bytes in cache for marks.
22struct MarksWeightFunction
23{
24 size_t operator()(const MarksInCompressedFile & marks) const
25 {
26 /// NOTE Could add extra 100 bytes for overhead of std::vector, cache structures and allocator.
27 return marks.size() * sizeof(MarkInCompressedFile);
28 }
29};
30
31
32/** Cache of 'marks' for StorageMergeTree.
33 * Marks is an index structure that addresses ranges in column file, corresponding to ranges of primary key.
34 */
35class MarkCache : public LRUCache<UInt128, MarksInCompressedFile, UInt128TrivialHash, MarksWeightFunction>
36{
37private:
38 using Base = LRUCache<UInt128, MarksInCompressedFile, UInt128TrivialHash, MarksWeightFunction>;
39
40public:
41 MarkCache(size_t max_size_in_bytes)
42 : Base(max_size_in_bytes) {}
43
44 /// Calculate key from path to file and offset.
45 static UInt128 hash(const String & path_to_file)
46 {
47 UInt128 key;
48
49 SipHash hash;
50 hash.update(path_to_file.data(), path_to_file.size() + 1);
51 hash.get128(key.low, key.high);
52
53 return key;
54 }
55
56 template <typename LoadFunc>
57 MappedPtr getOrSet(const Key & key, LoadFunc && load)
58 {
59 auto result = Base::getOrSet(key, load);
60 if (result.second)
61 ProfileEvents::increment(ProfileEvents::MarkCacheMisses);
62 else
63 ProfileEvents::increment(ProfileEvents::MarkCacheHits);
64
65 return result.first;
66 }
67};
68
69using MarkCachePtr = std::shared_ptr<MarkCache>;
70
71}
72