Skip to content

Commit e13a27d

Browse files
authored
Merge pull request #346 from BigVan/main
[feat.] a new tool 'overlaybd-merge'
2 parents 1059cf4 + 99b3160 commit e13a27d

File tree

11 files changed

+293
-7
lines changed

11 files changed

+293
-7
lines changed

src/image_file.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <photon/fs/aligned-file.h>
2929
#include <photon/fs/localfs.h>
3030
#include "overlaybd/lsmt/file.h"
31+
#include "overlaybd/lsmt/index.h"
3132
#include "overlaybd/zfile/zfile.h"
3233
#include "config.h"
3334
#include "image_file.h"
@@ -515,6 +516,10 @@ int ImageFile::init_image_file() {
515516
return -1;
516517
}
517518

519+
int ImageFile::compact(IFile *as) {
520+
return ((LSMT::IFileRO*)m_file)->flatten(as);
521+
}
522+
518523
void ImageFile::set_auth_failed() {
519524
if (m_status == 0) // only set exit in image boot phase
520525
{

src/image_file.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ class ImageFile : public photon::fs::ForwardFile {
109109
return m_file;
110110
}
111111

112+
int compact(IFile *as);
113+
112114
private:
113115
Prefetcher *m_prefetcher = nullptr;
114116
ImageConfigNS::ImageConfig conf;
@@ -126,5 +128,7 @@ class ImageFile : public photon::fs::ForwardFile {
126128
IFile *__open_ro_target_file(const std::string &);
127129
IFile *__open_ro_remote(const std::string &dir, const std::string &, const uint64_t, int);
128130
IFile *__open_ro_target_remote(const std::string &dir, const std::string &, const uint64_t, int);
131+
132+
// size_t seek_data(off_t begin, off_t end);
129133
void start_bk_dl_thread();
130134
};

src/image_service.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class ImageService {
5858
// bool enable_acceleration(GlobalFs *global_fs, ImageConfigNS::P2PConfig conf);
5959
bool enable_acceleration();
6060

61+
6162
ImageConfigNS::GlobalConfig global_conf;
6263
struct GlobalFs global_fs;
6364
std::unique_ptr<OverlayBDMetric> metrics;

src/overlaybd/lsmt/file.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ struct HeaderTrailer {
177177
} __attribute__((packed));
178178

179179
class LSMTReadOnlyFile;
180+
static int merge_files_ro(vector<IFile *> files, const CommitArgs &args);
180181
static LSMTReadOnlyFile *open_file_ro(IFile *file, bool ownership, bool reserve_tag);
181182
static HeaderTrailer *verify_ht(IFile *file, char *buf, bool is_trailer = false,
182183
ssize_t st_size = -1);
@@ -642,6 +643,33 @@ class LSMTReadOnlyFile : public IFileRW {
642643
ret.valid_data_size = size;
643644
return ret;
644645
}
646+
647+
virtual ssize_t seek_data(off_t begin, off_t end, vector<Segment> &segs) override {
648+
649+
begin /= ALIGNMENT;
650+
end /= ALIGNMENT;
651+
while (begin < end) {
652+
SegmentMapping mappings[128];
653+
auto length = (end - begin < Segment::MAX_LENGTH ? end - begin : Segment::MAX_LENGTH);
654+
Segment s{(uint64_t)begin, (uint32_t)length};
655+
auto find = m_index->lookup(s, mappings, 128);
656+
if (find == 0) {
657+
begin+=length;
658+
continue;
659+
}
660+
segs.insert(segs.end(), mappings, mappings + find);
661+
begin=mappings[find-1].end();
662+
663+
}
664+
return segs.size();
665+
}
666+
667+
virtual int flatten(IFile *as) override{
668+
CommitArgs args(as);
669+
vector<IFile*> files = m_files;
670+
reverse(files.begin(), files.end());
671+
return merge_files_ro(files, args);
672+
}
645673
};
646674

647675
class LSMTFile : public LSMTReadOnlyFile {
@@ -956,6 +984,15 @@ class LSMTFile : public LSMTReadOnlyFile {
956984
data_stat.valid_data_size);
957985
return data_stat;
958986
}
987+
988+
virtual int flatten(IFile *as) override {
989+
990+
unique_ptr<IComboIndex> pmi((IComboIndex*)(m_index->make_read_only_index()));
991+
CommitArgs args(as);
992+
atomic_uint64_t _no_use_var(0);
993+
CompactOptions opts(&m_files, (SegmentMapping*)(pmi->buffer()), pmi->size(), m_vsize, &args);
994+
return compact(opts, _no_use_var);
995+
}
959996
};
960997
class LSMTSparseFile : public LSMTFile {
961998
public:
@@ -1677,7 +1714,7 @@ IFileRO *open_files_ro(IFile **files, size_t n, bool ownership) {
16771714
return rst;
16781715
}
16791716

1680-
int merge_files_ro(vector<IFile *> files, const CommitArgs &args) {
1717+
static int merge_files_ro(vector<IFile *> files, const CommitArgs &args) {
16811718
uint64_t vsize;
16821719
vector<UUID> files_uuid(files.size());
16831720
auto pmi = unique_ptr<IMemoryIndex>(load_merge_index(files, files_uuid, vsize));

src/overlaybd/lsmt/file.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ class IFileRO : public photon::fs::VirtualReadOnlyFile {
5050
virtual int get_uuid(UUID &out, size_t layer_idx = 0) const = 0;
5151

5252
virtual std::vector<IFile *> get_lower_files() const = 0;
53+
54+
virtual ssize_t seek_data(off_t begin, off_t end, std::vector<Segment> &segs) = 0;
55+
56+
virtual int flatten(IFile *as) = 0;
57+
5358
};
5459

5560
struct CommitArgs {
@@ -70,7 +75,6 @@ struct CommitArgs {
7075
class IFileRW : public IFileRO {
7176
public:
7277
virtual IMemoryIndex0 *index() const override = 0;
73-
7478
const int Index_Group_Commit = 10;
7579

7680
static const int RemoteData = 11;
@@ -96,6 +100,7 @@ class IFileRW : public IFileRO {
96100
uint64_t valid_data_size = -1; // size of valid data (excluding garbage)
97101
};
98102
virtual DataStat data_stat() const = 0;
103+
99104
};
100105

101106
// create a new writable LSMT file constitued by a data file and an index file,

src/overlaybd/lsmt/index.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ class Index : public IMemoryIndex {
153153
uint64_t vsize() const override {
154154
return virtual_size;
155155
}
156+
157+
UNIMPLEMENTED_POINTER(IMemoryIndex *make_read_only_index() const override);
156158
};
157159

158160
class LevelIndex : public Index {
@@ -254,6 +256,8 @@ class Index0 : public IComboIndex {
254256
}
255257
} alloc_blk;
256258

259+
// Index0(const set<SegmentMapping> &mapping) : mapping(mapping){};
260+
257261
Index0(const SegmentMapping *pmappings = nullptr, size_t n = 0) {
258262
if (pmappings == nullptr)
259263
return;
@@ -505,6 +509,21 @@ class ComboIndex : public Index0 {
505509
merge_indexes(0, mappings, indexes, 2, 0, UINT64_MAX, false, max_level);
506510
return new Index(std::move(mappings));
507511
}
512+
513+
virtual Index *make_read_only_index() const override{
514+
vector<SegmentMapping> mappings;
515+
auto ro_idx0 = new Index;
516+
ro_idx0->ownership = false;
517+
ro_idx0->assign(mapping.begin(), mapping.end());
518+
if (m_backing_index == nullptr) {
519+
return ro_idx0;
520+
}
521+
const Index *indexes[2] = {ro_idx0, const_cast<Index *>(m_backing_index)};
522+
merge_indexes(0, mappings, indexes, 2, 0, UINT64_MAX, false, 2);
523+
delete ro_idx0;
524+
return new Index(std::move(mappings));
525+
}
526+
508527
};
509528

510529
//======================== END OF ComboIndex =============================//

src/overlaybd/lsmt/index.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ class IMemoryIndex {
128128
virtual uint64_t block_count() const = 0;
129129

130130
virtual uint64_t vsize() const = 0;
131+
132+
virtual IMemoryIndex *make_read_only_index() const = 0;
131133
};
132134

133135
// the level 0 memory index, which supports write
@@ -139,7 +141,7 @@ class IMemoryIndex0 : public IMemoryIndex {
139141
// dump the the whole index as an array
140142
// memory allocation is aligned to the `alignment`
141143
virtual SegmentMapping *dump(size_t alignment = 0) const = 0;
142-
virtual IMemoryIndex *make_read_only_index() const = 0;
144+
// virtual IMemoryIndex *make_read_only_index() const = 0;
143145
};
144146

145147
class IComboIndex : public IMemoryIndex0 {
@@ -153,6 +155,8 @@ class IComboIndex : public IMemoryIndex0 {
153155
// and then clear the original index0.
154156
// virtual IMemoryIndex0* gc_index() = 0;
155157
virtual IMemoryIndex *load_range_index(int, int) const = 0;
158+
159+
156160
};
157161

158162
// create writable level 0 memory index from an array of mappings;

src/overlaybd/lsmt/test/test.cpp

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,26 +584,70 @@ TEST_F(FileTest3, stack_files) {
584584
cout << "merging RO layers as " << fn_merged << endl;
585585
auto merged = lfs->open(fn_merged, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
586586
merge_files_ro(files, FLAGS_layers, merged);
587-
/*auto mergedro =*/::open_file_ro(merged, true);
587+
auto mergedro =::open_file_ro(merged, true);
588588
cout << "verifying merged RO layers file" << endl;
589+
verify_file(mergedro);
590+
delete mergedro;
589591
cout << "verifying stacked RO layers file" << endl;
590592
auto lower = open_files_ro(files, FLAGS_layers);
591593
verify_file(lower);
592594
((LSMTReadOnlyFile *)lower)->m_index =
593595
create_level_index(lower->index()->buffer(), lower->index()->size(), 0, UINT64_MAX, false);
594596
EXPECT_EQ(((LSMTReadOnlyFile *)lower)->close_seal(), -1);
595597
CommitArgs _(nullptr);
596-
EXPECT_EQ(((LSMTReadOnlyFile *)lower)->commit(_), -1);
597598
auto stat = ((LSMTReadOnlyFile *)lower)->data_stat();
598599
LOG_INFO("RO valid data: `", stat.valid_data_size);
600+
merged = lfs->open(fn_merged, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
601+
EXPECT_EQ(lower->flatten(merged), 0);
602+
cout << "verifying flattened layer of lowers" << endl;
603+
verify_file(fn_merged);
604+
delete merged;
605+
cout << "generating a RW layer by randwrite()" << endl;
606+
auto upper = create_file_rw();
607+
auto file = stack_files(upper, lower, 0, true);
608+
randwrite(file, FLAGS_nwrites);
609+
verify_file(file);
610+
cout << "verifying flattened layer of stacked layers" << endl;
611+
612+
merged = lfs->open(fn_merged, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
613+
file->flatten(merged);
614+
verify_file(fn_merged);
615+
delete file;
616+
}
617+
618+
TEST_F(FileTest3, seek_data) {
619+
CleanUp();
620+
cout << "generating " << FLAGS_layers << " RO layers by randwrite()" << endl;
621+
for (int i = 0; i < FLAGS_layers; ++i) {
622+
files[i] = create_commit_layer(0, ut_io_engine);
623+
}
624+
625+
auto lower = open_files_ro(files, FLAGS_layers);
626+
verify_file(lower);
627+
((LSMTReadOnlyFile *)lower)->m_index =
628+
create_level_index(lower->index()->buffer(), lower->index()->size(), 0, UINT64_MAX, false);
599629
cout << "generating a RW layer by randwrite()" << endl;
600630
auto upper = create_file_rw();
601631
auto file = stack_files(upper, lower, 0, true);
602632
randwrite(file, FLAGS_nwrites);
603633
verify_file(file);
634+
635+
auto fmerged = create_file_rw();
636+
vector<Segment> segs;
637+
auto data = new char[8<<20];
638+
file->seek_data(0, vsize, segs);
639+
LOG_INFO("flattern segments count: `", segs.size());
640+
for (auto m : segs) {
641+
auto readn = file->pread(data, m.length*ALIGNMENT, m.offset * ALIGNMENT);
642+
EXPECT_EQ(readn, fmerged->pwrite(data, readn, m.offset * ALIGNMENT));
643+
}
644+
verify_file(fmerged);
604645
delete file;
646+
delete fmerged;
647+
delete[] data;
605648
}
606649

650+
607651
TEST_F(FileTest3, sparsefile_close_seal) {
608652
CleanUp();
609653
cout << "generating " << FLAGS_layers << " RO layers by randwrite()" << endl;

src/overlaybd/zfile/zfile.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "compressor.h"
3434
#include <atomic>
3535
#include <thread>
36+
#include "photon/thread/thread11.h"
3637

3738
using namespace photon::fs;
3839

@@ -938,6 +939,16 @@ class ZFileBuilderMP : public ZFileBuilderBase {
938939
UNIMPLEMENTED(int fstat(struct stat *buf) override);
939940
};
940941

942+
ssize_t read_chunk(IFile *file, char *buf, off_t offset, size_t length, ssize_t *result) {
943+
LOG_DEBUG("read zfile index chunk {offset: `, len: `}", offset, length);
944+
if (file->pread(buf, length, offset) != (ssize_t)length) {
945+
*result = -1;
946+
LOG_ERRNO_RETURN(0, -1, "failed to read index chunk {offset: `, len: `}.", offset, length);
947+
}
948+
*result = 0;
949+
return 0;
950+
}
951+
941952
bool load_jump_table(IFile *file, CompressionFile::HeaderTrailer *pheader_trailer,
942953
CompressionFile::JumpTable &jump_table, bool trailer = true) {
943954
char buf[CompressionFile::HeaderTrailer::SPACE];
@@ -994,8 +1005,25 @@ bool load_jump_table(IFile *file, CompressionFile::HeaderTrailer *pheader_traile
9941005
}
9951006
auto ibuf = std::unique_ptr<uint32_t[]>(new uint32_t[pht->index_size]);
9961007
LOG_DEBUG("index_offset: `", pht->index_offset);
997-
ret = file->pread((void *)(ibuf.get()), index_bytes, pht->index_offset);
998-
if (ret < (ssize_t)index_bytes) {
1008+
1009+
size_t delta = 1UL<<20;
1010+
std::vector<photon::join_handle*> ths;
1011+
ssize_t *r = new ssize_t[index_bytes / delta + 1]{};
1012+
DEFER(delete []r);
1013+
int idx = 0;
1014+
for (off_t offset = 0; offset < (off_t)index_bytes; offset += delta) {
1015+
size_t chunk_size = std::min(index_bytes - offset, delta);
1016+
auto th = photon::thread_create11(&ZFile::read_chunk, file, (char*)ibuf.get() + offset, pht->index_offset + offset, chunk_size, &r[idx++]);
1017+
ths.push_back(photon::thread_enable_join(th));
1018+
}
1019+
ret = 0;
1020+
for (int i =0; i<idx; i++){
1021+
photon::thread_join(ths[i]);
1022+
if (r[i]!=0) {
1023+
ret = -1;
1024+
}
1025+
}
1026+
if (ret != 0) {
9991027
LOG_ERRNO_RETURN(0, false, "failed to read index");
10001028
}
10011029
if (pht->is_digest_enabled()) {

src/tools/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ add_executable(overlaybd-commit overlaybd-commit.cpp)
22
target_include_directories(overlaybd-commit PUBLIC ${PHOTON_INCLUDE_DIR})
33
target_link_libraries(overlaybd-commit photon_static overlaybd_image_lib)
44

5+
add_executable(overlaybd-merge overlaybd-merge.cpp)
6+
target_include_directories(overlaybd-merge PUBLIC ${PHOTON_INCLUDE_DIR})
7+
target_link_libraries(overlaybd-merge photon_static overlaybd_image_lib)
8+
9+
510
add_executable(overlaybd-create overlaybd-create.cpp)
611
target_include_directories(overlaybd-create PUBLIC ${PHOTON_INCLUDE_DIR})
712
target_link_libraries(overlaybd-create photon_static overlaybd_lib)
@@ -30,6 +35,8 @@ install(TARGETS
3035
overlaybd-create
3136
overlaybd-zfile
3237
overlaybd-apply
38+
overlaybd-merge
39+
3340
turboOCI-apply
3441
DESTINATION /opt/overlaybd/bin
3542
)

0 commit comments

Comments
 (0)