Skip to content

Commit 6e12ba2

Browse files
authored
Storages: Shutdown the LocalIndexScheduler before shutting down PageStorage/DeltaMergeStore (release-8.5) (#9713)
close #9714 Storages: Shutdown the LocalIndexScheduler before shutting down PageStorage/DeltaMergeStore * Add a method `LocalIndexerScheduler::shutdown()` and ensure the running task are all finished before shutting down the GlobalPageStorage in `ContextShared::shutdown()`. Signed-off-by: JaySon-Huang <tshent@qq.com>
1 parent 990562e commit 6e12ba2

File tree

6 files changed

+111
-27
lines changed

6 files changed

+111
-27
lines changed

dbms/src/Interpreters/Context.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,13 @@ struct ContextShared
271271
return;
272272
shutdown_called = true;
273273

274+
// The local index scheduler must be shutdown to stop all
275+
// running tasks before shutting down `global_storage_pool`.
276+
if (global_local_indexer_scheduler)
277+
{
278+
global_local_indexer_scheduler->shutdown();
279+
}
280+
274281
if (global_storage_pool)
275282
{
276283
// shutdown the gc task of global storage pool before

dbms/src/Interpreters/executeQuery.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ std::tuple<ASTPtr, BlockIO> executeQueryImpl(
311311

312312
if (elem.read_rows != 0)
313313
{
314-
LOG_INFO(
314+
LOG_DEBUG(
315315
execute_query_logger,
316316
"Read {} rows, {} in {:.3f} sec., {} rows/sec., {}/sec.",
317317
elem.read_rows,
@@ -421,7 +421,7 @@ void logQueryPipeline(const LoggerPtr & logger, const BlockInputStreamPtr & in)
421421
in->dumpTree(log_buffer);
422422
return log_buffer.toString();
423423
};
424-
LOG_INFO(logger, pipeline_log_str());
424+
LOG_DEBUG(logger, pipeline_log_str());
425425
}
426426

427427
BlockIO executeQuery(const String & query, Context & context, bool internal, QueryProcessingStage::Enum stage)

dbms/src/Storages/DeltaMerge/LocalIndexerScheduler.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ LocalIndexerScheduler::LocalIndexerScheduler(const Options & options)
6464
start();
6565
}
6666

67-
LocalIndexerScheduler::~LocalIndexerScheduler()
67+
void LocalIndexerScheduler::shutdown()
6868
{
69-
LOG_INFO(logger, "LocalIndexerScheduler is destroying. Waiting scheduler and tasks to finish...");
69+
LOG_INFO(logger, "LocalIndexerScheduler is shutting down. Waiting scheduler and tasks to finish...");
7070

7171
// First quit the scheduler. Don't schedule more tasks.
7272
is_shutting_down = true;
@@ -81,7 +81,15 @@ LocalIndexerScheduler::~LocalIndexerScheduler()
8181

8282
// Then wait all running tasks to finish.
8383
pool.reset();
84+
LOG_INFO(logger, "LocalIndexerScheduler is shutdown.");
85+
}
8486

87+
LocalIndexerScheduler::~LocalIndexerScheduler()
88+
{
89+
if (!is_shutting_down)
90+
{
91+
shutdown();
92+
}
8593
LOG_INFO(logger, "LocalIndexerScheduler is destroyed");
8694
}
8795

@@ -295,7 +303,10 @@ bool LocalIndexerScheduler::tryAddTaskToPool(std::unique_lock<std::mutex> & lock
295303
}
296304
};
297305

298-
RUNTIME_CHECK(pool);
306+
if (is_shutting_down || !pool)
307+
// shutting down, retry again
308+
return false;
309+
299310
if (!pool->trySchedule(real_job))
300311
// Concurrent task limit reached
301312
return false;

dbms/src/Storages/DeltaMerge/LocalIndexerScheduler.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ class LocalIndexerScheduler
9393

9494
~LocalIndexerScheduler();
9595

96+
/**
97+
* @brief Stop the scheduler and wait for running tasks to finish.
98+
* Note that this method won't clear the task pushed.
99+
*/
100+
void shutdown();
101+
96102
/**
97103
* @brief Start the scheduler. In some tests we need to start scheduler
98104
* after some tasks are pushed.
@@ -101,7 +107,7 @@ class LocalIndexerScheduler
101107

102108
/**
103109
* @brief Blocks until there is no tasks remaining in the queue and there is no running tasks.
104-
* Should be only used in tests.
110+
* **Should be only used in tests**.
105111
*/
106112
void waitForFinish();
107113

@@ -114,6 +120,7 @@ class LocalIndexerScheduler
114120

115121
/**
116122
* @brief Drop all tasks matching specified keyspace id and table id.
123+
* Note that this method won't drop the running tasks.
117124
*/
118125
size_t dropTasks(KeyspaceID keyspace_id, TableID table_id);
119126

@@ -147,9 +154,6 @@ class LocalIndexerScheduler
147154
void moveBackReadyTasks(std::unique_lock<std::mutex> & lock);
148155

149156
private:
150-
bool is_started = false;
151-
std::thread scheduler_thread;
152-
153157
/// Try to add a task to the pool. Returns false if the pool is full
154158
/// (for example, reaches concurrent task limit or memory limit).
155159
/// When pool is full, we will not try to schedule any more tasks at this moment.
@@ -160,6 +164,9 @@ class LocalIndexerScheduler
160164
/// heavy pressure.
161165
bool tryAddTaskToPool(std::unique_lock<std::mutex> & lock, const InternalTaskPtr & task);
162166

167+
std::thread scheduler_thread;
168+
bool is_started = false;
169+
163170
KeyspaceID last_schedule_keyspace_id = 0;
164171
std::map<KeyspaceID, TableID> last_schedule_table_id_by_ks;
165172

dbms/src/Storages/DeltaMerge/Segment.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -417,24 +417,34 @@ SegmentPtr Segment::restoreSegment( //
417417
DMContext & context,
418418
PageIdU64 segment_id)
419419
{
420-
Page page = context.storage_pool->metaReader()->read(segment_id); // not limit restore
421-
422-
ReadBufferFromMemory buf(page.data.begin(), page.data.size());
423420
Segment::SegmentMetaInfo segment_info;
424-
readSegmentMetaInfo(buf, segment_info);
421+
try
422+
{
423+
Page page = context.storage_pool->metaReader()->read(segment_id); // not limit restore
425424

426-
auto delta = DeltaValueSpace::restore(context, segment_info.range, segment_info.delta_id);
427-
auto stable = StableValueSpace::restore(context, segment_info.stable_id);
428-
auto segment = std::make_shared<Segment>(
429-
parent_log,
430-
segment_info.epoch,
431-
segment_info.range,
432-
segment_id,
433-
segment_info.next_segment_id,
434-
delta,
435-
stable);
425+
ReadBufferFromMemory buf(page.data.begin(), page.data.size());
426+
readSegmentMetaInfo(buf, segment_info);
436427

437-
return segment;
428+
auto delta = DeltaValueSpace::restore(context, segment_info.range, segment_info.delta_id);
429+
auto stable = StableValueSpace::restore(context, segment_info.stable_id);
430+
auto segment = std::make_shared<Segment>(
431+
parent_log,
432+
segment_info.epoch,
433+
segment_info.range,
434+
segment_id,
435+
segment_info.next_segment_id,
436+
delta,
437+
stable);
438+
439+
return segment;
440+
}
441+
catch (DB::Exception & e)
442+
{
443+
e.addMessage(fmt::format("while restoreSegment, segment_id={}", segment_id));
444+
e.rethrow();
445+
}
446+
RUNTIME_CHECK_MSG(false, "unreachable");
447+
return {};
438448
}
439449

440450
Segment::SegmentMetaInfos Segment::readAllSegmentsMetaInfoInRange( //

dbms/src/Storages/Page/tools/PageCtl/PageStorageCtlV3.cpp

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#include <Common/Checksum.h>
1516
#include <IO/Encryption/MockKeyManager.h>
1617
#include <Interpreters/Context.h>
1718
#include <Poco/ConsoleChannel.h>
1819
#include <Poco/PatternFormatter.h>
1920
#include <Server/CLIService.h>
21+
#include <Storages/Page/PageDefinesBase.h>
22+
#include <Storages/Page/V3/PageDefines.h>
2023
#include <Storages/Page/V3/PageDirectory.h>
2124
#include <Storages/Page/V3/PageDirectoryFactory.h>
2225
#include <Storages/Page/V3/PageStorageImpl.h>
2326
#include <Storages/Page/V3/Universal/RaftDataReader.h>
27+
#include <Storages/Page/V3/Universal/UniversalPageId.h>
2428
#include <Storages/Page/V3/Universal/UniversalPageIdFormatImpl.h>
2529
#include <Storages/Page/V3/Universal/UniversalPageStorage.h>
2630
#include <Storages/PathPool.h>
@@ -29,6 +33,7 @@
2933
#include <common/types.h>
3034

3135
#include <boost/program_options.hpp>
36+
#include <cstdint>
3237
#include <magic_enum.hpp>
3338
#include <unordered_set>
3439

@@ -47,12 +52,15 @@ struct ControlOptions
4752
CHECK_ALL_DATA_CRC = 4,
4853
DISPLAY_WAL_ENTRIES = 5,
4954
DISPLAY_REGION_INFO = 6,
55+
DISPLAY_BLOB_DATA = 7,
5056
};
5157

5258
std::vector<std::string> paths;
5359
DisplayType mode = DisplayType::DISPLAY_SUMMARY_INFO;
5460
UInt64 page_id = UINT64_MAX;
5561
UInt32 blob_id = UINT32_MAX;
62+
BlobFileOffset blob_offset = INVALID_BLOBFILE_OFFSET;
63+
size_t blob_size = UINT64_MAX;
5664
UInt64 namespace_id = DB::TEST_NAMESPACE_ID;
5765
StorageType storage_type = StorageType::Unknown; // only useful for universal page storage
5866
UInt32 keyspace_id = NullspaceID; // only useful for universal page storage
@@ -85,6 +93,7 @@ ControlOptions ControlOptions::parse(int argc, char ** argv)
8593
4 is check every data is valid
8694
5 is dump entries in WAL log files
8795
6 is display all region info
96+
7 is display blob data (in hex)
8897
)") //
8998
("show_entries",
9099
value<bool>()->default_value(true),
@@ -106,8 +115,14 @@ ControlOptions ControlOptions::parse(int argc, char ** argv)
106115
value<UInt64>()->default_value(UINT64_MAX),
107116
"Query a single Page id, and print its version chain.") //
108117
("blob_id,B",
109-
value<UInt32>()->default_value(UINT32_MAX),
110-
"Query a single Blob id, and print its data distribution.") //
118+
value<BlobFileId>()->default_value(INVALID_BLOBFILE_ID),
119+
"Specify the blob_id") //
120+
("blob_offset",
121+
value<BlobFileOffset>()->default_value(INVALID_BLOBFILE_OFFSET),
122+
"Specify the offset.") //
123+
("blob_size",
124+
value<size_t>()->default_value(0),
125+
"Specify the size.") //
111126
//
112127
("imitative,I",
113128
value<bool>()->default_value(true),
@@ -140,7 +155,9 @@ ControlOptions ControlOptions::parse(int argc, char ** argv)
140155
opt.paths = options["paths"].as<std::vector<std::string>>();
141156
auto mode_int = options["mode"].as<int>();
142157
opt.page_id = options["page_id"].as<UInt64>();
143-
opt.blob_id = options["blob_id"].as<UInt32>();
158+
opt.blob_id = options["blob_id"].as<BlobFileId>();
159+
opt.blob_offset = options["blob_offset"].as<BlobFileOffset>();
160+
opt.blob_size = options["blob_size"].as<size_t>();
144161
opt.show_entries = options["show_entries"].as<bool>();
145162
opt.check_fields = options["check_fields"].as<bool>();
146163
auto storage_type_int = options["storage_type"].as<int>();
@@ -346,6 +363,12 @@ class PageStorageControlV3
346363
}
347364
break;
348365
}
366+
case ControlOptions::DisplayType::DISPLAY_BLOB_DATA:
367+
{
368+
String hex_data = getBlobData(blob_store, opts.blob_id, opts.blob_offset, opts.blob_size);
369+
fmt::println("hex:{}", hex_data);
370+
break;
371+
}
349372
default:
350373
std::cout << "Invalid display mode." << std::endl;
351374
break;
@@ -821,6 +844,32 @@ class PageStorageControlV3
821844
return error_msg.toString();
822845
}
823846

847+
static String getBlobData(
848+
typename Trait::BlobStore & blob_store,
849+
BlobFileId blob_id,
850+
BlobFileOffset offset,
851+
size_t size)
852+
{
853+
auto page_id = []() {
854+
if constexpr (std::is_same_v<Trait, u128::PageStorageControlV3Trait>)
855+
return PageIdV3Internal(0, 0);
856+
else
857+
return UniversalPageId("");
858+
}();
859+
char * buffer = new char[size];
860+
blob_store.read(page_id, blob_id, offset, buffer, size, nullptr, false);
861+
862+
using ChecksumClass = Digest::CRC64;
863+
ChecksumClass digest;
864+
digest.update(buffer, size);
865+
auto checksum = digest.checksum();
866+
fmt::println("checksum: 0x{:X}", checksum);
867+
868+
auto hex_str = Redact::keyToHexString(buffer, size);
869+
delete[] buffer;
870+
return hex_str;
871+
}
872+
824873
private:
825874
ControlOptions options;
826875
};

0 commit comments

Comments
 (0)