17
17
#include < Poco/ConsoleChannel.h>
18
18
#include < Poco/PatternFormatter.h>
19
19
#include < Server/CLIService.h>
20
+ #include < Storages/Page/PageDefinesBase.h>
21
+ #include < Storages/Page/V3/PageDefines.h>
20
22
#include < Storages/Page/V3/PageDirectory.h>
21
23
#include < Storages/Page/V3/PageDirectoryFactory.h>
22
24
#include < Storages/Page/V3/PageStorageImpl.h>
23
25
#include < Storages/Page/V3/Universal/RaftDataReader.h>
26
+ #include < Storages/Page/V3/Universal/UniversalPageId.h>
24
27
#include < Storages/Page/V3/Universal/UniversalPageIdFormatImpl.h>
25
28
#include < Storages/Page/V3/Universal/UniversalPageStorage.h>
26
29
#include < Storages/PathPool.h>
29
32
#include < common/types.h>
30
33
31
34
#include < boost/program_options.hpp>
35
+ #include < cstdint>
32
36
#include < magic_enum.hpp>
33
37
#include < unordered_set>
34
38
@@ -47,12 +51,15 @@ struct ControlOptions
47
51
CHECK_ALL_DATA_CRC = 4 ,
48
52
DISPLAY_WAL_ENTRIES = 5 ,
49
53
DISPLAY_REGION_INFO = 6 ,
54
+ DISPLAY_BLOB_DATA = 7 ,
50
55
};
51
56
52
57
std::vector<std::string> paths;
53
58
DisplayType mode = DisplayType::DISPLAY_SUMMARY_INFO;
54
59
UInt64 page_id = UINT64_MAX;
55
- UInt32 blob_id = UINT32_MAX;
60
+ BlobFileId blob_id = INVALID_BLOBFILE_ID;
61
+ BlobFileOffset blob_offset = INVALID_BLOBFILE_OFFSET;
62
+ size_t blob_size = UINT64_MAX;
56
63
UInt64 namespace_id = DB::TEST_NAMESPACE_ID;
57
64
StorageType storage_type = StorageType::Unknown; // only useful for universal page storage
58
65
UInt32 keyspace_id = NullspaceID; // only useful for universal page storage
@@ -85,6 +92,7 @@ ControlOptions ControlOptions::parse(int argc, char ** argv)
85
92
4 is check every data is valid
86
93
5 is dump entries in WAL log files
87
94
6 is display all region info
95
+ 7 is display blob data (in hex)
88
96
)" ) //
89
97
(" show_entries" ,
90
98
value<bool >()->default_value (true ),
@@ -106,8 +114,14 @@ ControlOptions ControlOptions::parse(int argc, char ** argv)
106
114
value<UInt64>()->default_value (UINT64_MAX),
107
115
" Query a single Page id, and print its version chain." ) //
108
116
(" blob_id,B" ,
109
- value<UInt32>()->default_value (UINT32_MAX),
110
- " Query a single Blob id, and print its data distribution." ) //
117
+ value<BlobFileId>()->default_value (INVALID_BLOBFILE_ID),
118
+ " Specify the blob_id" ) //
119
+ (" blob_offset" ,
120
+ value<BlobFileOffset>()->default_value (INVALID_BLOBFILE_OFFSET),
121
+ " Specify the offset." ) //
122
+ (" blob_size" ,
123
+ value<size_t >()->default_value (0 ),
124
+ " Specify the size." ) //
111
125
//
112
126
(" imitative,I" ,
113
127
value<bool >()->default_value (true ),
@@ -140,7 +154,9 @@ ControlOptions ControlOptions::parse(int argc, char ** argv)
140
154
opt.paths = options[" paths" ].as <std::vector<std::string>>();
141
155
auto mode_int = options[" mode" ].as <int >();
142
156
opt.page_id = options[" page_id" ].as <UInt64>();
143
- opt.blob_id = options[" blob_id" ].as <UInt32>();
157
+ opt.blob_id = options[" blob_id" ].as <BlobFileId>();
158
+ opt.blob_offset = options[" blob_offset" ].as <BlobFileOffset>();
159
+ opt.blob_size = options[" blob_size" ].as <size_t >();
144
160
opt.show_entries = options[" show_entries" ].as <bool >();
145
161
opt.check_fields = options[" check_fields" ].as <bool >();
146
162
auto storage_type_int = options[" storage_type" ].as <int >();
@@ -346,6 +362,12 @@ class PageStorageControlV3
346
362
}
347
363
break ;
348
364
}
365
+ case ControlOptions::DisplayType::DISPLAY_BLOB_DATA:
366
+ {
367
+ String hex_data = getBlobData (blob_store, opts.blob_id , opts.blob_offset , opts.blob_size );
368
+ fmt::print (" hex:{}\n " , hex_data);
369
+ break ;
370
+ }
349
371
default :
350
372
std::cout << " Invalid display mode." << std::endl;
351
373
break ;
@@ -372,7 +394,7 @@ class PageStorageControlV3
372
394
return 0 ;
373
395
}
374
396
375
- static String getBlobsInfo (typename Trait::BlobStore & blob_store, UInt32 blob_id)
397
+ static String getBlobsInfo (typename Trait::BlobStore & blob_store, BlobFileId blob_id)
376
398
{
377
399
auto stat_info = [](const BlobStats::BlobStatPtr & stat, const String & path) {
378
400
FmtBuffer stat_str;
@@ -402,7 +424,7 @@ class PageStorageControlV3
402
424
{
403
425
for (const auto & stat : stats)
404
426
{
405
- if (blob_id != UINT32_MAX )
427
+ if (blob_id != INVALID_BLOBFILE_ID )
406
428
{
407
429
if (stat->id == blob_id)
408
430
{
@@ -416,7 +438,7 @@ class PageStorageControlV3
416
438
}
417
439
}
418
440
419
- if (blob_id != UINT32_MAX )
441
+ if (blob_id != INVALID_BLOBFILE_ID )
420
442
{
421
443
stats_info.fmtAppend (" no found blob {}" , blob_id);
422
444
}
@@ -447,34 +469,41 @@ class PageStorageControlV3
447
469
size_t count = 0 ;
448
470
for (const auto & [version, entry_or_del] : versioned_entries->entries )
449
471
{
450
- const auto & entry = entry_or_del.entry ;
451
- page_str.fmtAppend (
452
- " entry {}\n "
453
- " sequence: {}\n "
454
- " epoch: {}\n "
455
- " is del: {}\n "
456
- " blob id: {}\n "
457
- " offset: {}\n "
458
- " size: {}\n "
459
- " crc: 0x{:X}\n " , //
460
- count++, //
461
- version.sequence , //
462
- version.epoch , //
463
- entry_or_del.isDelete (), //
464
- entry.file_id , //
465
- entry.offset , //
466
- entry.size , //
467
- entry.checksum , //
468
- entry.field_offsets .size () //
469
- );
470
- if (!entry.field_offsets .empty ())
472
+ if (entry_or_del.isEntry ())
471
473
{
472
- page_str.append (" field offset:\n " );
473
- for (const auto & [offset, crc] : entry.field_offsets )
474
+ const auto & entry = entry_or_del.entry ;
475
+ page_str.fmtAppend (
476
+ " entry {}\n "
477
+ " sequence: {}\n "
478
+ " epoch: {}\n "
479
+ " is del: false\n "
480
+ " blob id: {}\n "
481
+ " offset: {}\n "
482
+ " size: {}\n "
483
+ " crc: 0x{:X}\n " , //
484
+ count++, //
485
+ version.sequence , //
486
+ version.epoch , //
487
+ entry.file_id , //
488
+ entry.offset , //
489
+ entry.size , //
490
+ entry.checksum , //
491
+ entry.field_offsets .size () //
492
+ );
493
+ if (!entry.field_offsets .empty ())
474
494
{
475
- page_str.fmtAppend (" offset: {} crc: 0x{:X}\n " , offset, crc);
495
+ page_str.append (" field offset:\n " );
496
+ for (const auto & [offset, crc] : entry.field_offsets )
497
+ {
498
+ page_str.fmtAppend (" offset: {} crc: 0x{:X}\n " , offset, crc);
499
+ }
500
+ page_str.append (" \n " );
476
501
}
477
- page_str.append (" \n " );
502
+ }
503
+ else
504
+ {
505
+ page_str.append (" entry is null\n "
506
+ " is del: true\n " );
478
507
}
479
508
}
480
509
return page_str.toString ();
@@ -814,6 +843,32 @@ class PageStorageControlV3
814
843
return error_msg.toString ();
815
844
}
816
845
846
+ static String getBlobData (
847
+ typename Trait::BlobStore & blob_store,
848
+ BlobFileId blob_id,
849
+ BlobFileOffset offset,
850
+ size_t size)
851
+ {
852
+ auto page_id = []() {
853
+ if constexpr (std::is_same_v<Trait, u128 ::PageStorageControlV3Trait>)
854
+ return PageIdV3Internal (0 , 0 );
855
+ else
856
+ return UniversalPageId (" " );
857
+ }();
858
+ char * buffer = new char [size];
859
+ blob_store.read (page_id, blob_id, offset, buffer, size, nullptr , false );
860
+
861
+ using ChecksumClass = Digest::CRC64;
862
+ ChecksumClass digest;
863
+ digest.update (buffer, size);
864
+ auto checksum = digest.checksum ();
865
+ fmt::print (" checksum: 0x{:X}\n " , checksum);
866
+
867
+ auto hex_str = Redact::keyToHexString (buffer, size);
868
+ delete[] buffer;
869
+ return hex_str;
870
+ }
871
+
817
872
private:
818
873
ControlOptions options;
819
874
};
0 commit comments