-
Notifications
You must be signed in to change notification settings - Fork 170
/
Copy pathreal_dirty_memory_accounter.hh
82 lines (73 loc) · 2.83 KB
/
real_dirty_memory_accounter.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
* Copyright (C) 2018 ScyllaDB
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "memtable.hh"
#include "row_cache.hh"
#include "dirty_memory_manager.hh"
// makes sure that cache update handles real dirty memory correctly.
class real_dirty_memory_accounter {
dirty_memory_manager& _mgr;
cache_tracker& _tracker;
uint64_t _bytes;
uint64_t _uncommitted = 0;
public:
real_dirty_memory_accounter(dirty_memory_manager& mgr, cache_tracker& tracker, size_t size);
real_dirty_memory_accounter(memtable& m, cache_tracker& tracker);
~real_dirty_memory_accounter();
real_dirty_memory_accounter(real_dirty_memory_accounter&& c);
real_dirty_memory_accounter(const real_dirty_memory_accounter& c) = delete;
// Needs commit() to take effect, or when this object is destroyed.
void unpin_memory(uint64_t bytes) { _uncommitted += bytes; }
void commit();
};
inline
real_dirty_memory_accounter::real_dirty_memory_accounter(dirty_memory_manager& mgr, cache_tracker& tracker, size_t size)
: _mgr(mgr)
, _tracker(tracker)
, _bytes(size) {
_mgr.pin_real_dirty_memory(_bytes);
}
inline
real_dirty_memory_accounter::real_dirty_memory_accounter(memtable& m, cache_tracker& tracker)
: real_dirty_memory_accounter(m.get_dirty_memory_manager(), tracker, m.occupancy().used_space())
{ }
inline
real_dirty_memory_accounter::~real_dirty_memory_accounter() {
_mgr.unpin_real_dirty_memory(_bytes);
}
inline
real_dirty_memory_accounter::real_dirty_memory_accounter(real_dirty_memory_accounter&& c)
: _mgr(c._mgr), _tracker(c._tracker), _bytes(c._bytes), _uncommitted(c._uncommitted) {
c._bytes = 0;
c._uncommitted = 0;
}
inline
void real_dirty_memory_accounter::commit() {
auto bytes = std::exchange(_uncommitted, 0);
// this should never happen - if it does it is a bug. But we'll try to recover and log
// instead of asserting. Once it happens, though, it can keep happening until the update is
// done. So using metrics is better-suited than printing to the logs
if (bytes > _bytes) {
_tracker.pinned_dirty_memory_overload(bytes - _bytes);
}
auto delta = std::min(bytes, _bytes);
_bytes -= delta;
_mgr.unpin_real_dirty_memory(delta);
}