Skip to content

Commit 7e81fc1

Browse files
author
Xun Chen
committed
Implement create_snapshot interface for ImageFile
Signed-off-by: Xun Chen <xunchen@hust.edu.cn>
1 parent 02600d1 commit 7e81fc1

File tree

7 files changed

+352
-16
lines changed

7 files changed

+352
-16
lines changed

src/image_file.cpp

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,12 +334,12 @@ LSMT::IFileRO *ImageFile::open_lowers(std::vector<ImageConfigNS::LayerConfig> &l
334334
return NULL;
335335

336336
photon::join_handle *ths[PARALLEL_LOAD_INDEX];
337-
std::vector<IFile *> files;
337+
std::vector<IFile *> files; // layer0 ... layerN-1
338338
files.resize(lowers.size(), nullptr);
339339
auto n = std::min(PARALLEL_LOAD_INDEX, (int)lowers.size());
340340
LOG_DEBUG("create ` photon threads to open lowers", n);
341341

342-
ParallelOpenTask tm(files, lowers.size(), lowers);
342+
ParallelOpenTask tm(files, lowers.size(), lowers); // layer0 ... layerN-1
343343
for (auto i = 0; i < n; ++i) {
344344
ths[i] =
345345
photon::thread_enable_join(photon::thread_create11(&do_parallel_open_files, this, tm));
@@ -443,7 +443,7 @@ int ImageFile::init_image_file() {
443443
ImageConfigNS::UpperConfig upper;
444444
bool record_no_download = false;
445445
bool has_error = false;
446-
auto lowers = conf.lowers();
446+
auto lowers = conf.lowers(); // layer0 ... layerN-1
447447
auto concurrency = image_service.global_conf.prefetchConfig().concurrency();
448448

449449
if (conf.accelerationLayer() && !conf.recordTracePath().empty()) {
@@ -554,3 +554,51 @@ void ImageFile::set_failed(const Ts &...xs) {
554554
m_exception = estring().appends(xs...);
555555
}
556556
}
557+
558+
int ImageFile::create_snapshot(const char *config_path) {
559+
// load new config file to get the snapshot layer path
560+
// open new upper layer
561+
// restack() current RW layer as snapshot layer
562+
if(!m_lower_file || !m_upper_file)
563+
LOG_ERROR_RETURN(0, -1, "Lower or upper layer is NULL.");
564+
565+
ImageConfigNS::ImageConfig new_cfg;
566+
LSMT::IFileRW *upper_file = nullptr;
567+
568+
LOG_INFO("Load new config `.", config_path);
569+
if (!new_cfg.ParseJSON(config_path)) {
570+
LOG_ERROR_RETURN(0, -1, "Error parse new config json: `.", config_path);
571+
}
572+
573+
auto upper = new_cfg.upper();
574+
auto lowers = new_cfg.lowers();
575+
if(lowers[lowers.size()-1].file() != conf.upper().data())
576+
LOG_ERROR_RETURN(0, -1, "The last lower layer(`) should be the same as old upper layer(`) after restack.", lowers[lowers.size()-1].file(), conf.upper().data());
577+
if(upper.index() == conf.upper().index() || upper.data() == conf.upper().data())
578+
LOG_ERROR_RETURN(0, -1, "The new upper layer(`, `) should be different from the old upper layer(`, `).", upper.data(), upper.index(), conf.upper().data(), conf.upper().index());
579+
580+
upper_file = open_upper(upper);
581+
if (!upper_file)
582+
LOG_ERROR_RETURN(0, -1, "Open upper layer failed.");
583+
584+
if(((LSMT::IFileRW *)m_file)->restack(upper_file) != 0)
585+
LOG_ERRNO_RETURN(0, -1, "Restack new rwlayer failed.");
586+
587+
if(m_upper_file) {
588+
// transfer the sealed layer from m_upper_file to m_lower_file before m_upper_file is destructed
589+
auto sealed = ((LSMT::IFileRW *)m_upper_file)->get_file(0);
590+
((LSMT::IFileRO *)m_lower_file)->insert_file(sealed);
591+
((LSMT::IFileRW *)m_upper_file)->clear_files();
592+
delete m_upper_file;
593+
}
594+
// set m_lower_file->m_index = m_file->m_index->m_backing_index because m_file is not responsible for the destruction of m_backing_index
595+
auto combo_index = (LSMT::IComboIndex *)((LSMT::IFileRW *)m_file)->index(); // m_file->m_index
596+
((LSMT::IFileRO *)m_lower_file)->index(combo_index->backing_index());
597+
// set m_file->m_index->m_index0 = upper_file->m_index
598+
auto upper_file_index = (LSMT::IMemoryIndex0 *)((LSMT::IFileRW *)upper_file)->index(); // upper_file->m_index
599+
combo_index->front_index(upper_file_index);
600+
601+
m_upper_file = upper_file;
602+
603+
return 0;
604+
}

src/image_file.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ class ImageFile : public photon::fs::ForwardFile {
8282
return ret;
8383
}
8484

85+
ssize_t pwrite(const void *buf, size_t count, off_t offset) override
86+
{
87+
return m_file->pwrite(buf, count, offset);
88+
}
89+
90+
ssize_t pread(void *buf, size_t count, off_t offset) override
91+
{
92+
return m_file->pread(buf, count, offset);
93+
}
94+
8595
ssize_t pwritev(const struct iovec *iov, int iovcnt, off_t offset) override {
8696
if (read_only) {
8797
LOG_ERROR_RETURN(EROFS, -1, "writing read only file");
@@ -119,13 +129,7 @@ class ImageFile : public photon::fs::ForwardFile {
119129

120130
int compact(IFile *as);
121131

122-
int create_snapshot(const char *config_path) {
123-
// load new config file to get the snapshot layer path
124-
// open new upper layer
125-
// restack() current RW layer as snapshot layer
126-
LOG_INFO("call create_snapshot, dev_id: `", m_dev_id);
127-
return 0;
128-
}
132+
int create_snapshot(const char *config_path);
129133

130134
private:
131135
Prefetcher *m_prefetcher = nullptr;

src/overlaybd/lsmt/file.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,20 @@ class LSMTReadOnlyFile : public IFileRW {
500500
return (IMemoryIndex0 *)m_index;
501501
}
502502

503+
virtual int index(const IMemoryIndex *index) override {
504+
if(!index || !index->buffer()) {
505+
errno = EINVAL;
506+
LOG_ERROR("Invalid index!");
507+
return -1;
508+
}
509+
if (m_index != nullptr) {
510+
delete m_index;
511+
m_index = nullptr;
512+
}
513+
m_index = (IMemoryIndex *)index;
514+
return 0;
515+
}
516+
503517
virtual int close() override {
504518
safe_delete(m_index);
505519
if (m_file_ownership) {
@@ -523,6 +537,23 @@ class LSMTReadOnlyFile : public IFileRW {
523537
return m_files;
524538
}
525539

540+
virtual IFile *get_file(size_t file_idx) const override {
541+
if (file_idx >= m_files.size()) {
542+
LOG_ERROR_RETURN(0, nullptr, "file_idx out of range.");
543+
}
544+
return m_files[file_idx];
545+
}
546+
547+
virtual int insert_file(IFile * file) override {
548+
m_files.insert(m_files.begin(), file);
549+
return 0;
550+
}
551+
552+
virtual int clear_files() override {
553+
m_files.clear();
554+
return 0;
555+
}
556+
526557
template <typename T1, typename T2, typename T3>
527558
inline void forward(void *&buffer, T1 &offset, T2 &count, T3 step) {
528559
(char *&)buffer += step * ALIGNMENT;
@@ -1038,6 +1069,9 @@ class LSMTFile : public LSMTReadOnlyFile {
10381069
m_findex = u->m_findex;
10391070
m_vsize = u->m_vsize;
10401071
((IComboIndex *)m_index)->commit_index0();
1072+
1073+
delete fseal;
1074+
delete gc_layer;
10411075
return 0;
10421076
}
10431077

@@ -1333,7 +1367,7 @@ static SegmentMapping *do_load_index(IFile *file, HeaderTrailer *pheader_trailer
13331367
auto ret = file->fstat(&stat);
13341368
if (ret < 0)
13351369
LOG_ERRNO_RETURN(0, nullptr, "failed to stat file.");
1336-
assert(pht->is_sparse_rw() == false);
1370+
assert(trailer || pht->is_sparse_rw() == false);
13371371
uint64_t index_bytes;
13381372
if (trailer) {
13391373
if (!pht->is_data_file())
@@ -1738,7 +1772,7 @@ static IMemoryIndex *load_merge_index(vector<IFile *> &files, vector<UUID> &uuid
17381772
}
17391773
}
17401774

1741-
std::reverse(files.begin(), files.end());
1775+
std::reverse(files.begin(), files.end()); // reverse files: layerN-1 ... layer0
17421776
std::reverse(tm.indexes.begin(), tm.indexes.end());
17431777
std::reverse(uuid.begin(), uuid.end());
17441778
auto pmi = merge_memory_indexes((const IMemoryIndex **)&tm.indexes[0], tm.indexes.size());

src/overlaybd/lsmt/file.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,19 @@ class IFileRO : public photon::fs::VirtualReadOnlyFile {
4646

4747
virtual IMemoryIndex *index() const = 0;
4848

49+
virtual int index(const IMemoryIndex *index) = 0;
50+
4951
// return uuid of m_files[layer_idx];
5052
virtual int get_uuid(UUID &out, size_t layer_idx = 0) const = 0;
5153

5254
virtual std::vector<IFile *> get_lower_files() const = 0;
5355

56+
virtual IFile *get_file(size_t file_idx) const = 0;
57+
58+
virtual int insert_file(IFile * file) = 0;
59+
60+
virtual int clear_files() = 0;
61+
5462
virtual ssize_t seek_data(off_t begin, off_t end, std::vector<Segment> &segs) = 0;
5563

5664
virtual int flatten(IFile *as) = 0;

src/overlaybd/lsmt/index.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ class Index0 : public IComboIndex {
617617
virtual const IMemoryIndex0 *front_index() const override {
618618
return this;
619619
}
620+
UNIMPLEMENTED(int front_index(const IMemoryIndex0 *fi) override);
620621
UNIMPLEMENTED(size_t vsize() const override);
621622
UNIMPLEMENTED(int commit_index0() override);
622623
};
@@ -649,6 +650,19 @@ class ComboIndex : public Index0 {
649650
}
650651
}
651652

653+
virtual int front_index(const IMemoryIndex0 *fi) override {
654+
if (!fi) {
655+
errno = EINVAL;
656+
LOG_ERROR("Invalid index!");
657+
return -1;
658+
}
659+
if (m_ownership && m_index0 != nullptr) { // !!!
660+
delete m_index0;
661+
m_index0 = nullptr;
662+
}
663+
m_index0 = (Index0 *)fi;
664+
return 0;
665+
}
652666
virtual const IMemoryIndex0 *front_index() const override {
653667
return this->m_index0;
654668
}
@@ -759,7 +773,8 @@ class ComboIndex : public Index0 {
759773
p.tag = 0;
760774
merged_index->insert(p);
761775
}
762-
delete m_backing_index;
776+
if(m_ownership) // !!!
777+
delete m_backing_index;
763778
m_backing_index = (Index*)(merged_index->make_read_only_index()); // set ownership=false
764779
delete merged_index;
765780
LOG_INFO("rebuild backing index done. {count: `}", m_backing_index->size());

src/overlaybd/lsmt/index.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class IComboIndex : public IMemoryIndex0 {
149149
// backing index must NOT be IMemoryIndex0!
150150
virtual int backing_index(const IMemoryIndex *bi) = 0;
151151
virtual const IMemoryIndex *backing_index() const = 0;
152+
virtual int front_index(const IMemoryIndex0 *fi) = 0;
152153
virtual const IMemoryIndex0 *front_index() const = 0;
153154

154155
// dump index0 which needs to compact

0 commit comments

Comments
 (0)