aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Storages/MergeTree/BackgroundProcessList.h
blob: c9a4887cca3fd5d04539907eaf214c08031503a4 (plain) (blame)
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
83
84
85
86
87
88
89
90
91
92
93
#pragma once

#include <Common/CurrentMetrics.h>
#include <memory>
#include <list>
#include <mutex>
#include <atomic>

namespace DB
{

/// Common code for background processes lists, like system.merges and system.replicated_fetches
/// Look at examples in MergeList, MovesList and ReplicatedFetchList

template <typename ListElement, typename Info>
class BackgroundProcessList;

template <typename ListElement, typename Info>
class BackgroundProcessListEntry
{
    BackgroundProcessList<ListElement, Info> & list;
    using container_t = std::list<ListElement>;
    typename container_t::iterator it;
    CurrentMetrics::Increment metric_increment;
public:
    BackgroundProcessListEntry(const BackgroundProcessListEntry &) = delete;
    BackgroundProcessListEntry & operator=(const BackgroundProcessListEntry &) = delete;

    BackgroundProcessListEntry(BackgroundProcessListEntry &&) noexcept = default;

    BackgroundProcessListEntry(BackgroundProcessList<ListElement, Info> & list_, const typename container_t::iterator it_, const CurrentMetrics::Metric & metric)
        : list(list_), it{it_}, metric_increment{metric}
    {
        list.onEntryCreate(*this);
    }

    ~BackgroundProcessListEntry()
    {
        std::lock_guard lock{list.mutex};
        list.onEntryDestroy(*this);
        list.entries.erase(it);
    }

    ListElement * operator->() { return &*it; }
    const ListElement * operator->() const { return &*it; }
};


template <typename ListElement, typename Info>
class BackgroundProcessList
{
protected:
    friend class BackgroundProcessListEntry<ListElement, Info>;

    using container_t = std::list<ListElement>;
    using info_container_t = std::list<Info>;

    mutable std::mutex mutex;
    container_t entries;

    CurrentMetrics::Metric metric;

    explicit BackgroundProcessList(const CurrentMetrics::Metric & metric_)
        : metric(metric_)
    {}
public:

    using Entry = BackgroundProcessListEntry<ListElement, Info>;
    using EntryPtr = std::unique_ptr<Entry>;

    template <typename... Args>
    EntryPtr insert(Args &&... args)
    {
        std::lock_guard lock{mutex};
        auto entry = std::make_unique<Entry>(*this, entries.emplace(entries.end(), std::forward<Args>(args)...), metric);
        return entry;
    }

    info_container_t get() const
    {
        std::lock_guard lock{mutex};
        info_container_t res;
        for (const auto & list_element : entries)
            res.emplace_back(list_element.getInfo());
        return res;
    }

    virtual void onEntryCreate(const Entry & /* entry */) {}
    virtual void onEntryDestroy(const Entry & /* entry */) {}
    virtual inline ~BackgroundProcessList() = default;
};

}