aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Storages/MergeTree/MergeTreePartsMover.h
blob: 82fd271ee5f692145aabb31ea178f90c58ea91bb (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
#pragma once

#include <functional>
#include <optional>
#include <vector>
#include <base/scope_guard.h>
#include <Disks/StoragePolicy.h>
#include <Storages/MergeTree/IMergeTreeDataPart.h>
#include <Storages/MergeTree/MovesList.h>
#include <Common/ActionBlocker.h>

namespace DB
{

enum class MovePartsOutcome
{
    PartsMoved,
    NothingToMove,
    MovesAreCancelled,
    MoveWasPostponedBecauseOfZeroCopy,
};

/// Active part from storage and destination reservation where it has to be moved
struct MergeTreeMoveEntry
{
    std::shared_ptr<const IMergeTreeDataPart> part;
    ReservationPtr reserved_space;

    MergeTreeMoveEntry(const std::shared_ptr<const IMergeTreeDataPart> & part_, ReservationPtr reservation_)
        : part(part_), reserved_space(std::move(reservation_))
    {
    }
};

using MergeTreeMovingParts = std::vector<MergeTreeMoveEntry>;

/** Can select parts for background moves, clone them to appropriate disks into
 * /detached directory and replace them into active parts set
 */
class MergeTreePartsMover
{
private:
    /// Callback tells that part is not participating in background process
    using AllowedMovingPredicate = std::function<bool(const std::shared_ptr<const IMergeTreeDataPart> &, String * reason)>;

public:

    explicit MergeTreePartsMover(MergeTreeData * data_)
        : data(data_)
        , log(&Poco::Logger::get("MergeTreePartsMover"))
    {
    }

    struct TemporaryClonedPart
    {
        MergeTreeMutableDataPartPtr part;
        scope_guard temporary_directory_lock;
    };

    /// Select parts for background moves according to storage_policy configuration.
    /// Returns true if at least one part was selected for move.
    bool selectPartsForMove(
        MergeTreeMovingParts & parts_to_move,
        const AllowedMovingPredicate & can_move,
        const std::lock_guard<std::mutex> & moving_parts_lock);

    /// Copies part to selected reservation in detached folder. Throws exception if part already exists.
    TemporaryClonedPart clonePart(const MergeTreeMoveEntry & moving_part) const;

    /// Replaces cloned part from detached directory into active data parts set.
    /// Replacing part changes state to DeleteOnDestroy and will be removed from disk after destructor of
    /// IMergeTreeDataPart called. If replacing part doesn't exists or not active (committed) than
    /// cloned part will be removed and log message will be reported. It may happen in case of concurrent
    /// merge or mutation.
    void swapClonedPart(TemporaryClonedPart & cloned_part) const;

    /// Can stop background moves and moves from queries
    ActionBlocker moves_blocker;

private:

    MergeTreeData * data;
    Poco::Logger * log;
};


}