Coverage Report

Created: 2026-07-08 03:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/cloud/cloud_delta_writer.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "cloud/cloud_delta_writer.h"
19
20
#include "cloud/cloud_meta_mgr.h"
21
#include "cloud/cloud_rowset_builder.h"
22
#include "cloud/cloud_storage_engine.h"
23
#include "cloud/config.h"
24
#include "load/delta_writer/delta_writer.h"
25
#include "load/memtable/memtable_memory_limiter.h"
26
#include "runtime/exec_env.h"
27
#include "runtime/thread_context.h"
28
29
namespace doris {
30
31
bvar::Adder<int64_t> g_cloud_commit_rowset_count("cloud_commit_rowset_count");
32
bvar::Adder<int64_t> g_cloud_commit_empty_rowset_count("cloud_commit_empty_rowset_count");
33
34
CloudDeltaWriter::CloudDeltaWriter(CloudStorageEngine& engine, const WriteRequest& req,
35
                                   RuntimeProfile* profile, const UniqueId& load_id)
36
269k
        : BaseDeltaWriter(req, profile, load_id), _engine(engine) {
37
269k
    _rowset_builder = std::make_unique<CloudRowsetBuilder>(engine, req, profile);
38
269k
    _resource_ctx = thread_context()->resource_ctx();
39
269k
}
40
41
269k
CloudDeltaWriter::~CloudDeltaWriter() = default;
42
43
31.3k
Status CloudDeltaWriter::batch_init(std::vector<CloudDeltaWriter*> writers) {
44
31.3k
    if (writers.empty()) {
45
0
        return Status::OK();
46
0
    }
47
48
31.3k
    std::vector<std::function<Status()>> tasks;
49
31.3k
    tasks.reserve(writers.size());
50
112k
    for (auto* writer : writers) {
51
112k
        if (writer->_is_init || writer->_is_cancelled) {
52
58.4k
            continue;
53
58.4k
        }
54
55
54.3k
        tasks.emplace_back([writer] {
56
54.2k
            SCOPED_ATTACH_TASK(writer->resource_context());
57
54.2k
            std::lock_guard<bthread::Mutex> lock(writer->_mtx);
58
54.2k
            if (writer->_is_init || writer->_is_cancelled) {
59
0
                return Status::OK();
60
0
            }
61
54.2k
            Status st = writer->init(); // included in SCOPED_ATTACH_TASK
62
54.2k
            return st;
63
54.2k
        });
64
54.3k
    }
65
66
31.3k
    return cloud::bthread_fork_join(tasks, 10);
67
31.3k
}
68
69
Status CloudDeltaWriter::write(const Block* block, const DorisVector<uint32_t>& row_idxs,
70
114k
                               bool* memtable_flushed) {
71
114k
    if (memtable_flushed != nullptr) {
72
114k
        *memtable_flushed = false;
73
114k
    }
74
114k
    if (row_idxs.empty()) [[unlikely]] {
75
0
        return Status::OK();
76
0
    }
77
114k
    if (_req.enable_table_memtable_backpressure && !_req.is_high_priority) {
78
4.35k
        ExecEnv::GetInstance()->memtable_memory_limiter()->handle_table_memtable_backpressure(
79
4.35k
                [this]() {
80
0
                    std::lock_guard lock(_mtx);
81
0
                    return _is_cancelled;
82
0
                },
83
4.35k
                table_id());
84
4.35k
    }
85
114k
    std::lock_guard lock(_mtx);
86
114k
    CHECK(_is_init || _is_cancelled);
87
114k
    {
88
114k
        SCOPED_TIMER(_wait_flush_limit_timer);
89
114k
        while (_memtable_writer->flush_running_count() >=
90
114k
               config::memtable_flush_running_count_limit) {
91
0
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
92
0
        }
93
114k
    }
94
114k
    return _memtable_writer->write(block, row_idxs, memtable_flushed);
95
114k
}
96
97
54.3k
Status CloudDeltaWriter::close() {
98
54.3k
    std::lock_guard lock(_mtx);
99
54.3k
    CHECK(_is_init);
100
54.3k
    return _memtable_writer->close();
101
54.3k
}
102
103
0
Status CloudDeltaWriter::flush_memtable_async() {
104
0
    std::lock_guard lock(_mtx);
105
0
    return BaseDeltaWriter::flush_memtable_async();
106
0
}
107
108
93.9k
Status CloudDeltaWriter::cancel_with_status(const Status& st) {
109
93.9k
    std::lock_guard lock(_mtx);
110
93.9k
    return BaseDeltaWriter::cancel_with_status(st);
111
93.9k
}
112
113
54.3k
Status CloudDeltaWriter::build_rowset() {
114
54.3k
    std::lock_guard lock(_mtx);
115
54.3k
    CHECK(_is_init);
116
54.3k
    return BaseDeltaWriter::build_rowset();
117
54.3k
}
118
119
525k
CloudRowsetBuilder* CloudDeltaWriter::rowset_builder() {
120
525k
    return static_cast<CloudRowsetBuilder*>(_rowset_builder.get());
121
525k
}
122
123
175k
void CloudDeltaWriter::update_tablet_stats() {
124
175k
    rowset_builder()->update_tablet_stats();
125
175k
}
126
127
54.2k
const RowsetMetaSharedPtr& CloudDeltaWriter::rowset_meta() {
128
54.2k
    return rowset_builder()->rowset_meta();
129
54.2k
}
130
131
174k
Status CloudDeltaWriter::commit_rowset() {
132
174k
    g_cloud_commit_rowset_count << 1;
133
174k
    std::lock_guard<bthread::Mutex> lock(_mtx);
134
135
    // Handle empty rowset (no data written)
136
174k
    if (!_is_init) {
137
120k
        g_cloud_commit_empty_rowset_count << 1;
138
120k
        return _commit_empty_rowset();
139
120k
    }
140
141
    // Handle normal rowset with data
142
53.4k
    return _engine.meta_mgr().commit_rowset(*rowset_meta(), "",
143
53.4k
                                            _rowset_builder->tablet()->table_id());
144
174k
}
145
146
120k
Status CloudDeltaWriter::_commit_empty_rowset() {
147
    // If skip writing empty rowset metadata is enabled,
148
    // we do not prepare rowset to meta service.
149
120k
    if (config::skip_writing_empty_rowset_metadata) {
150
120k
        rowset_builder()->set_skip_writing_rowset_metadata(true);
151
120k
    }
152
153
120k
    RETURN_IF_ERROR(_rowset_builder->init());
154
120k
    RETURN_IF_ERROR(_rowset_builder->build_rowset());
155
156
    // If skip writing empty rowset metadata is enabled, we do not commit rowset to meta service.
157
120k
    if (config::skip_writing_empty_rowset_metadata) {
158
120k
        return Status::OK();
159
120k
    }
160
    // write a empty rowset kv to keep version continuous
161
189
    return _engine.meta_mgr().commit_rowset(*rowset_meta(), "",
162
189
                                            _rowset_builder->tablet()->table_id());
163
120k
}
164
165
175k
Status CloudDeltaWriter::set_txn_related_info() {
166
175k
    return rowset_builder()->set_txn_related_info();
167
175k
}
168
169
} // namespace doris