Skip to content

Commit fe037c6

Browse files
authored
Merge pull request #161 from liulanzheng/filecache
optimizations for vcpu and bump version v0.6.0
2 parents c7e6024 + 15db309 commit fe037c6

24 files changed

+656
-213
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.15)
22

33
project(
44
overlaybd
5-
VERSION 0.5.3
5+
VERSION 0.6.0
66
LANGUAGES C CXX
77
)
88
enable_language(C)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ Default configure file `overlaybd.json` is installed to `/etc/overlaybd/`.
147147
| logLevel | DEBUG 0, INFO 1, WARN 2, ERROR 3 |
148148
| ioEngine | IO engine used to open local files: psync 0, libaio 1, posix aio 2. |
149149
| logPath | The path for log file, `/var/log/overlaybd.log` is the default value. |
150-
| cacheConfig.cacheType | Cache type used, `file` and `ocf` are supported. |
150+
| cacheConfig.cacheType | Cache type used, `file`, `ocf` and `download` are supported. |
151151
| cacheConfig.cacheDir | The cache directory for remote image data. |
152152
| cacheConfig.cacheSizeGB | The max size of cache, in GB. |
153153
| cacheConfig.refillSize | The refill size from source, in byte. `262144` is default (256 KB). |

src/bk_download.cpp

Lines changed: 55 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16+
#include "bk_download.h"
1617
#include <errno.h>
1718
#include <list>
1819
#include <set>
@@ -24,13 +25,11 @@
2425
#include <photon/fs/localfs.h>
2526
#include <photon/fs/throttled-file.h>
2627
#include <photon/thread/thread.h>
27-
#include <photon/common/event-loop.h>
28-
#include <photon/io/fd-events.h>
29-
#include "bk_download.h"
30-
3128
#include <openssl/sha.h>
3229
#include <sys/stat.h>
3330
#include <unistd.h>
31+
#include "switch_file.h"
32+
3433
using namespace photon::fs;
3534

3635
static constexpr size_t ALIGNMENT = 4096;
@@ -90,57 +89,10 @@ bool check_downloaded(const std::string &dir) {
9089

9190
static std::set<std::string> lock_files;
9291

93-
ssize_t filecopy(IFile *infile, IFile *outfile, size_t bs, int retry_limit, int &running) {
94-
if (bs == 0)
95-
LOG_ERROR_RETURN(EINVAL, -1, "bs should not be 0");
96-
void *buff = nullptr;
97-
98-
// buffer allocate, with 4K alignment
99-
::posix_memalign(&buff, ALIGNMENT, bs);
100-
if (buff == nullptr)
101-
LOG_ERROR_RETURN(ENOMEM, -1, "Fail to allocate buffer with ", VALUE(bs));
102-
DEFER(free(buff));
103-
off_t offset = 0;
104-
ssize_t count = bs;
105-
while (count == (ssize_t)bs) {
106-
if (running != 1) {
107-
LOG_INFO("image file exit when background downloading");
108-
return -1;
109-
}
110-
111-
int retry = retry_limit;
112-
again_read:
113-
if (!(retry--))
114-
LOG_ERROR_RETURN(EIO, -1, "Fail to read at ", VALUE(offset), VALUE(count));
115-
auto rlen = infile->pread(buff, bs, offset);
116-
if (rlen < 0) {
117-
LOG_DEBUG("Fail to read at ", VALUE(offset), VALUE(count), " retry...");
118-
goto again_read;
119-
}
120-
retry = retry_limit;
121-
again_write:
122-
if (!(retry--))
123-
LOG_ERROR_RETURN(EIO, -1, "Fail to write at ", VALUE(offset), VALUE(count));
124-
// cause it might write into file with O_DIRECT
125-
// keep write length as bs
126-
auto wlen = outfile->pwrite(buff, bs, offset);
127-
// but once write lenth larger than read length treats as OK
128-
if (wlen < rlen) {
129-
LOG_DEBUG("Fail to write at ", VALUE(offset), VALUE(count), " retry...");
130-
goto again_write;
131-
}
132-
count = rlen;
133-
offset += count;
134-
}
135-
// truncate after write, for O_DIRECT
136-
outfile->ftruncate(offset);
137-
return offset;
138-
}
139-
14092
void BkDownload::switch_to_local_file() {
14193
std::string path = dir + "/" + COMMIT_FILE_NAME;
14294
((ISwitchFile *)sw_file)->set_switch_file(path.c_str());
143-
LOG_DEBUG("set switch tag done. (localpath: `)", path);
95+
LOG_DEBUG("set switch done. (localpath: `)", path);
14496
}
14597

14698
bool BkDownload::download_done() {
@@ -166,6 +118,7 @@ bool BkDownload::download_done() {
166118
photon::thread_usleep(-1UL);
167119
if (shares != digest) {
168120
LOG_ERROR("verify checksum ` failed (expect: `, got: `)", old_name, digest, shares);
121+
force_download = true; // force redownload next time
169122
return false;
170123
}
171124

@@ -224,13 +177,59 @@ bool BkDownload::download_blob(int &running) {
224177

225178
auto dst = open_localfile_adaptor(dl_file_path.c_str(), O_RDWR | O_CREAT, 0644);
226179
if (dst == nullptr) {
227-
LOG_ERRNO_RETURN(0, -1, "failed to open dst file `", dl_file_path.c_str());
180+
LOG_ERRNO_RETURN(0, false, "failed to open dst file `", dl_file_path.c_str());
228181
}
229182
DEFER(delete dst;);
183+
dst->ftruncate(file_size);
230184

231-
auto res = filecopy(src, dst, 1024UL * 1024, 1, running);
232-
if (res < 0)
233-
return false;
185+
size_t bs = 256 * 1024;
186+
off_t offset = 0;
187+
void *buff = nullptr;
188+
// buffer allocate, with 4K alignment
189+
::posix_memalign(&buff, ALIGNMENT, bs);
190+
if (buff == nullptr)
191+
LOG_ERRNO_RETURN(0, false, "failed to allocate buffer with ", VALUE(bs));
192+
DEFER(free(buff));
193+
194+
while (offset < file_size) {
195+
if (running != 1) {
196+
LOG_INFO("image file exit when background downloading");
197+
return false;
198+
}
199+
if (!force_download) {
200+
// check aleady downloaded.
201+
auto hole_pos = dst->lseek(offset, SEEK_HOLE);
202+
if (hole_pos >= offset + bs) {
203+
// alread downloaded
204+
offset += bs;
205+
continue;
206+
}
207+
}
208+
209+
int retry = 2;
210+
auto count = bs;
211+
if (offset + count > file_size)
212+
count = file_size - offset;
213+
again_read:
214+
if (!(retry--))
215+
LOG_ERROR_RETURN(EIO, false, "failed to read at ", VALUE(offset), VALUE(count));
216+
auto rlen = src->pread(buff, bs, offset);
217+
if (rlen < 0) {
218+
LOG_WARN("failed to read at ", VALUE(offset), VALUE(count), VALUE(errno), " retry...");
219+
goto again_read;
220+
}
221+
retry = 2;
222+
again_write:
223+
if (!(retry--))
224+
LOG_ERROR_RETURN(EIO, false, "failed to write at ", VALUE(offset), VALUE(count));
225+
auto wlen = dst->pwrite(buff, count, offset);
226+
// but once write lenth larger than read length treats as OK
227+
if (wlen < rlen) {
228+
LOG_WARN("failed to write at ", VALUE(offset), VALUE(count), VALUE(errno), " retry...");
229+
goto again_write;
230+
}
231+
offset += count;
232+
}
234233
return true;
235234
}
236235

src/bk_download.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,14 @@
1616
#pragma once
1717
#include <list>
1818
#include <string>
19-
#include "switch_file.h"
19+
#include <photon/fs/filesystem.h>
2020

2121
class ImageFile;
22+
class ISwitchFile;
2223

23-
namespace photon {
24-
namespace fs {
25-
class IFile;
26-
}
27-
}
2824
namespace BKDL {
2925

30-
static std::string DOWNLOAD_TMP_NAME = "overlaybd.download";
26+
static std::string DOWNLOAD_TMP_NAME = ".download";
3127
static std::string COMMIT_FILE_NAME = "overlaybd.commit";
3228

3329
bool check_downloaded(const std::string &dir);
@@ -46,10 +42,11 @@ class BkDownload {
4642
unlock_file();
4743
delete src_file;
4844
}
49-
BkDownload(ISwitchFile *sw_file, photon::fs::IFile *src_file, const std::string dir,
50-
int32_t limit_MB_ps, int32_t try_cnt, ImageFile *image_file, std::string digest)
51-
: sw_file(sw_file), src_file(src_file), dir(dir), limit_MB_ps(limit_MB_ps),
52-
try_cnt(try_cnt), image_file(image_file), digest(digest) {
45+
BkDownload(ISwitchFile *sw_file, photon::fs::IFile *src_file, size_t file_size,
46+
const std::string dir, int32_t limit_MB_ps, int32_t try_cnt, ImageFile *image_file,
47+
std::string digest)
48+
: sw_file(sw_file), src_file(src_file), file_size(file_size), dir(dir),
49+
limit_MB_ps(limit_MB_ps), try_cnt(try_cnt), image_file(image_file), digest(digest) {
5350
}
5451

5552
private:
@@ -62,6 +59,8 @@ class BkDownload {
6259
int32_t limit_MB_ps;
6360
ImageFile *image_file;
6461
std::string digest;
62+
size_t file_size;
63+
bool force_download = false;
6564
};
6665

6766
void bk_download_proc(std::list<BKDL::BkDownload *> &, uint64_t, int &);

src/image_file.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
#define PARALLEL_LOAD_INDEX 32
3838
using namespace photon::fs;
3939

40+
#define SET_LOCAL_DIR 118
41+
#define SET_SIZE 119
42+
4043
IFile *ImageFile::__open_ro_file(const std::string &path) {
4144
int flags = O_RDONLY;
4245

@@ -82,7 +85,7 @@ IFile *ImageFile::__open_ro_file(const std::string &path) {
8285
}
8386

8487
IFile *ImageFile::__open_ro_remote(const std::string &dir, const std::string &digest,
85-
const uint64_t size, int layer_index) {
88+
const uint64_t size, int layer_index) {
8689
std::string url;
8790
int64_t extra_range, rand_wait;
8891

@@ -118,6 +121,8 @@ IFile *ImageFile::__open_ro_remote(const std::string &dir, const std::string &di
118121
set_failed(err_msg);
119122
LOG_ERRNO_RETURN(0, nullptr, err_msg);
120123
}
124+
remote_file->ioctl(SET_SIZE, size);
125+
remote_file->ioctl(SET_LOCAL_DIR, dir);
121126

122127
ISwitchFile *switch_file = new_switch_file(remote_file);
123128
if (!switch_file) {
@@ -145,7 +150,7 @@ IFile *ImageFile::__open_ro_remote(const std::string &dir, const std::string &di
145150
LOG_WARN("failed to open source file, ignore download");
146151
} else {
147152
BKDL::BkDownload *obj =
148-
new BKDL::BkDownload(switch_file, srcfile, dir, conf.download().maxMBps(),
153+
new BKDL::BkDownload(switch_file, srcfile, size, dir, conf.download().maxMBps(),
149154
conf.download().tryCnt(), this, digest);
150155
LOG_DEBUG("add to download list for `", dir);
151156
dl_list.push_back(obj);

src/image_service.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@
2222
#include <photon/fs/localfs.h>
2323
#include <photon/net/curl.h>
2424
#include <photon/thread/thread.h>
25+
#include <photon/common/alog.h>
26+
#include <photon/net/curl.h>
27+
#include <photon/fs/path.h>
2528
#include "overlaybd/cache/cache.h"
2629
#include "overlaybd/registryfs/registryfs.h"
2730
#include "overlaybd/tar_file.h"
2831
#include "overlaybd/zfile/zfile.h"
2932
#include "overlaybd/base64.h"
30-
#include "photon/common/alog.h"
31-
#include "photon/net/curl.h"
3233
#include <errno.h>
3334
#include <fcntl.h>
3435
#include <limits.h>
@@ -254,6 +255,10 @@ void ImageService::set_result_file(std::string &filename, std::string &data) {
254255
data.c_str());
255256
}
256257

258+
static std::string cache_fn_trans_sha256(std::string_view path) {
259+
return std::string(photon::fs::Path(path).basename());
260+
}
261+
257262
int ImageService::init() {
258263
if (read_global_config_and_set() < 0) {
259264
return -1;
@@ -273,8 +278,8 @@ int ImageService::init() {
273278
refill_size = global_conf.cacheConfig().refillSize();
274279
block_size = global_conf.cacheConfig().blockSize();
275280

276-
if (cache_type != "file" && cache_type != "ocf") {
277-
LOG_ERROR_RETURN(0, -1, "unknown cache type `", cache_type);
281+
if (cache_type != "file" && cache_type != "ocf" && cache_type != "download") {
282+
LOG_ERROR_RETURN(0, -1, "unknown cache type: `", cache_type);
278283
}
279284
LOG_INFO("cache config: ", VALUE(cache_type), VALUE(cache_dir),
280285
VALUE(cache_size_GB), VALUE(refill_size));
@@ -302,11 +307,6 @@ int ImageService::init() {
302307
LOG_ERROR_RETURN(0, -1, "create registryfs failed.");
303308
}
304309

305-
auto tar_fs = new_tar_fs_adaptor(registry_fs);
306-
if (tar_fs == nullptr) {
307-
delete registry_fs;
308-
LOG_ERROR_RETURN(0, -1, "create tar_fs failed.");
309-
}
310310
global_fs.srcfs = registry_fs;
311311

312312
if (global_conf.p2pConfig().enable() == true) {
@@ -320,14 +320,13 @@ int ImageService::init() {
320320
if (cache_type == "file") {
321321
auto registry_cache_fs = new_localfs_adaptor(cache_dir.c_str());
322322
if (registry_cache_fs == nullptr) {
323-
delete tar_fs;
323+
delete global_fs.srcfs;
324324
LOG_ERROR_RETURN(0, -1, "new_localfs_adaptor for ` failed", cache_dir.c_str());
325325
}
326326
// file cache will delete its src_fs automatically when destructed
327327
global_fs.remote_fs = FileSystem::new_full_file_cached_fs(
328-
tar_fs, registry_cache_fs, refill_size /* refill unit 256KB */,
329-
cache_size_GB /*GB*/, 10000000,
330-
(uint64_t)1048576 * 4096, nullptr);
328+
global_fs.srcfs, registry_cache_fs, refill_size, cache_size_GB, 10000000,
329+
(uint64_t)1048576 * 4096, nullptr, cache_fn_trans_sha256);
331330

332331
} else if (cache_type == "ocf") {
333332
auto namespace_dir = std::string(cache_dir + "/namespace");
@@ -358,8 +357,12 @@ int ImageService::init() {
358357
}
359358
global_fs.media_file = media_file;
360359

361-
global_fs.remote_fs = FileSystem::new_ocf_cached_fs(tar_fs, namespace_fs, block_size, refill_size,
360+
global_fs.remote_fs = FileSystem::new_ocf_cached_fs(global_fs.srcfs, namespace_fs, block_size, refill_size,
362361
media_file, reload_media, io_alloc);
362+
} else if (cache_type == "download") {
363+
auto io_alloc = new IOAlloc;
364+
global_fs.io_alloc = io_alloc;
365+
global_fs.remote_fs = FileSystem::new_download_cached_fs(global_fs.srcfs, 4096, refill_size, io_alloc);
363366
}
364367

365368
if (global_fs.remote_fs == nullptr) {

src/overlaybd/cache/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_subdirectory(frontend)
22
add_subdirectory(full_file_cache)
33
add_subdirectory(ocf_cache)
4+
add_subdirectory(download_cache)
45

56
file(GLOB SRC_CACHE "*.cpp")
67

@@ -10,6 +11,7 @@ target_link_libraries(cache_lib
1011
cache_frontend_lib
1112
full_file_cache_lib
1213
ocf_cache_lib
14+
download_cache_lib
1315
)
1416
target_include_directories(cache_lib PUBLIC
1517
${PHOTON_INCLUDE_DIR}

src/overlaybd/cache/cache.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "full_file_cache/cache_pool.h"
2424

2525
namespace FileSystem {
26+
using namespace photon::fs;
27+
2628
ICacheStore::try_preadv_result ICacheStore::try_preadv(const struct iovec *iov, int iovcnt,
2729
off_t offset) {
2830
try_preadv_result rst;
@@ -60,7 +62,7 @@ ssize_t ICacheStore::pwritev_mutable(struct iovec *iov, int iovcnt, off_t offset
6062
ICachedFileSystem *new_full_file_cached_fs(IFileSystem *srcFs, IFileSystem *mediaFs,
6163
uint64_t refillUnit, uint64_t capacityInGB,
6264
uint64_t periodInUs, uint64_t diskAvailInBytes,
63-
IOAlloc *allocator) {
65+
IOAlloc *allocator, Fn_trans_func name_trans) {
6466
if (refillUnit % 4096 != 0) {
6567
LOG_ERROR_RETURN(EINVAL, nullptr, "refill Unit need to be aligned to 4KB")
6668
}
@@ -69,7 +71,7 @@ ICachedFileSystem *new_full_file_cached_fs(IFileSystem *srcFs, IFileSystem *medi
6971
}
7072
Cache::FileCachePool *pool = nullptr;
7173
pool =
72-
new ::Cache::FileCachePool(mediaFs, capacityInGB, periodInUs, diskAvailInBytes, refillUnit);
74+
new ::Cache::FileCachePool(mediaFs, capacityInGB, periodInUs, diskAvailInBytes, refillUnit, name_trans);
7375
pool->Init();
7476
return new_cached_fs(srcFs, pool, 4096, refillUnit, allocator);
7577
}

0 commit comments

Comments
 (0)