Skip to content

Commit 093be7b

Browse files
committed
Support manifest for WASMFS fetchfs
This way, a fetchfs WASMFS backend can have a mapping from paths to URLs used to satisfy those paths. I think this makes more sense than creating a separate fetchfs backend for each individual file. In the absence of a manifest, the old behavior of using the file path as a relative path against the baseURL will still be used. NOTE, it's important that the fetchfs have a dedicated directory created/"mounted" or else the "create file with path" code path will never be used. In other words, paths at `/whatever.txt` can never work given the way WASMFS is implemented; the accessed files don't get paths unless the parent directory and child path have the same backend. So, creating the directory at `/dat` and having a manifest entry like `/whatever.txt` is the way to go for a file at `/dat/whatever.txt`.
1 parent e2295ce commit 093be7b

File tree

4 files changed

+55
-15
lines changed

4 files changed

+55
-15
lines changed

src/library_fetchfs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ addToLibrary({
88
$FETCHFS__deps: ['$stringToUTF8OnStack', 'wasmfs_create_fetch_backend'],
99
$FETCHFS: {
1010
createBackend(opts) {
11-
return _wasmfs_create_fetch_backend(stringToUTF8OnStack(opts.base_url), opts.chunkSize | 0);
11+
return _wasmfs_create_fetch_backend(stringToUTF8OnStack(opts.base_url), opts.chunkSize | 0, 0);
1212
}
1313
},
1414
});

system/include/emscripten/wasmfs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ backend_t wasmfs_create_memory_backend(void);
5757
//
5858
// TODO: Add an async version of this function that will work on the main
5959
// thread.
60-
backend_t wasmfs_create_fetch_backend(const char* base_url __attribute__((nonnull)), uint32_t);
60+
backend_t wasmfs_create_fetch_backend(const char* base_url __attribute__((nonnull)), uint32_t, void *);
61+
62+
void *wasmfs_fetch_create_manifest();
63+
void wasmfs_fetch_add_to_manifest(void *, const char *, const char *);
6164

6265
backend_t wasmfs_create_node_backend(const char* root __attribute__((nonnull)));
6366

system/lib/wasmfs/backends/fetch_backend.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,32 @@ namespace wasmfs {
1515

1616
const uint32_t DEFAULT_CHUNK_SIZE = 16*1024*1024;
1717

18+
typedef std::map<std::string,std::string> FetchManifest;
19+
1820
class FetchBackend : public wasmfs::ProxiedAsyncJSBackend {
1921
std::string baseUrl;
2022
uint32_t chunkSize;
23+
FetchManifest *manifest;
2124
public:
25+
// Takes ownership of manifest
2226
FetchBackend(const std::string& baseUrl,
2327
uint32_t chunkSize,
28+
FetchManifest *manifest,
2429
std::function<void(backend_t)> setupOnThread)
25-
: ProxiedAsyncJSBackend(setupOnThread), baseUrl(baseUrl), chunkSize(chunkSize)
26-
// TODO manifest
30+
: ProxiedAsyncJSBackend(setupOnThread), baseUrl(baseUrl), chunkSize(chunkSize), manifest(manifest)
2731
{}
32+
~FetchBackend() {
33+
if(manifest != NULL) {
34+
delete manifest;
35+
}
36+
}
2837
std::shared_ptr<DataFile> createFile(mode_t mode) override;
2938
std::shared_ptr<Directory> createDirectory(mode_t mode) override;
3039
const std::string getFileURL(const std::string& filePath);
3140
uint32_t getChunkSize();
3241
};
3342

34-
43+
3544
class FetchFile : public ProxiedAsyncJSImplFile {
3645
std::string filePath;
3746
std::string fileUrl;
@@ -93,7 +102,11 @@ std::shared_ptr<Directory> FetchBackend::createDirectory(mode_t mode) {
93102
}
94103

95104
const std::string FetchBackend::getFileURL(const std::string& filePath) {
96-
// TODO use manifest
105+
if(manifest) {
106+
if (auto search = manifest->find(filePath); search != manifest->end()) {
107+
return baseUrl + "/" + search->second;
108+
}
109+
}
97110
if(filePath == "") {
98111
return baseUrl;
99112
}
@@ -104,15 +117,15 @@ uint32_t FetchBackend::getChunkSize() {
104117
}
105118

106119
extern "C" {
107-
backend_t wasmfs_create_fetch_backend(const char* base_url, uint32_t chunkSize /* TODO manifest */) {
120+
backend_t wasmfs_create_fetch_backend(const char* base_url, uint32_t chunkSize, FetchManifest *manifest) {
108121
// ProxyWorker cannot safely be synchronously spawned from the main browser
109122
// thread. See comment in thread_utils.h for more details.
110123
assert(!emscripten_is_main_browser_thread() &&
111124
"Cannot safely create fetch backend on main browser thread");
112125
return wasmFS.addBackend(std::make_unique<FetchBackend>(
113126
base_url ? base_url : "",
114127
chunkSize != 0 ? chunkSize : DEFAULT_CHUNK_SIZE,
115-
/* TODO manifest */
128+
manifest,
116129
[](backend_t backend) { _wasmfs_create_fetch_backend_js(backend); }));
117130
}
118131

@@ -128,6 +141,17 @@ uint32_t EMSCRIPTEN_KEEPALIVE _wasmfs_fetch_get_chunk_size(void* ptr) {
128141
auto* file = reinterpret_cast<wasmfs::FetchFile*>(ptr);
129142
return file ? file->getChunkSize() : DEFAULT_CHUNK_SIZE;
130143
}
144+
145+
void *EMSCRIPTEN_KEEPALIVE wasmfs_fetch_create_manifest() {
146+
return new FetchManifest();
147+
}
148+
void EMSCRIPTEN_KEEPALIVE wasmfs_fetch_add_to_manifest(void *manifest_ptr, const char *path, const char *url) {
149+
auto* manifest = reinterpret_cast<FetchManifest *>(manifest_ptr);
150+
auto path_str = std::string(path);
151+
auto url_str = std::string(url);
152+
manifest->insert(std::pair(path_str, url_str));
153+
}
154+
131155
}
132156

133157
} // namespace wasmfs

test/wasmfs/wasmfs_fetch.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,24 @@ void check_file(int fd, const char* content) {
4242
void test_url_relative() {
4343
printf("Running %s...\n", __FUNCTION__);
4444

45-
backend_t backend2 = wasmfs_create_fetch_backend("test.txt",0);
45+
backend_t backend2 = wasmfs_create_fetch_backend("test.txt",0,NULL);
4646
int fd = wasmfs_create_file("/file_rel", 0777, backend2);
4747
check_file(fd, "fetch 2");
4848
assert(close(fd) == 0);
4949
}
5050

51+
void test_manifest() {
52+
printf("Running %s...\n", __FUNCTION__);
53+
void *manifest = wasmfs_fetch_create_manifest();
54+
wasmfs_fetch_add_to_manifest(manifest, "/file", "test.txt");
55+
backend_t backend = wasmfs_create_fetch_backend("",0,manifest);
56+
// Create a directory with the fetchfs backend
57+
wasmfs_create_directory("/dat", 0777, backend);
58+
int fd = wasmfs_create_file("/dat/file", 0777, backend);
59+
check_file(fd, "fetch 2");
60+
assert(close(fd) == 0);
61+
}
62+
5163
void test_url_absolute() {
5264
printf("Running %s...\n", __FUNCTION__);
5365

@@ -56,7 +68,7 @@ void test_url_absolute() {
5668
char url[200];
5769
snprintf(url, sizeof(url), "%s%s", url_orig, file_name);
5870

59-
backend_t backend = wasmfs_create_fetch_backend(url,0);
71+
backend_t backend = wasmfs_create_fetch_backend(url,0,NULL);
6072
int fd = wasmfs_create_file(file_name, 0777, backend);
6173
check_file(fd, "fetch 2");
6274
assert(close(fd) == 0);
@@ -69,7 +81,7 @@ void test_directory_abs() {
6981
char url[200];
7082
snprintf(url, sizeof(url), "%s%s", url_orig, dir_path);
7183

72-
backend_t backend = wasmfs_create_fetch_backend(url,0);
84+
backend_t backend = wasmfs_create_fetch_backend(url,0,NULL);
7385
int res = wasmfs_create_directory(dir_path, 0777, backend);
7486
if (errno)
7587
perror("wasmfs_create_directory");
@@ -100,7 +112,7 @@ void test_directory_abs() {
100112

101113
void test_default() {
102114
printf("Running %s...\n", __FUNCTION__);
103-
backend_t backend = wasmfs_create_fetch_backend("data.dat",0);
115+
backend_t backend = wasmfs_create_fetch_backend("data.dat",0,NULL);
104116

105117
// Create a file in that backend.
106118
int fd = wasmfs_create_file("/testfile", 0777, backend);
@@ -136,7 +148,7 @@ void test_small_reads() {
136148
char expected[] = "hello";
137149
size_t size = 5;
138150

139-
backend_t backend = wasmfs_create_fetch_backend("small.dat",0);
151+
backend_t backend = wasmfs_create_fetch_backend("small.dat",0,NULL);
140152
int fd = wasmfs_create_file("/testfile3", 0777, backend);
141153
char buf[size + 1];
142154
for (size_t i = 0; i < size; i++) {
@@ -157,7 +169,7 @@ void test_small_chunks() {
157169
char expected[] = "hello";
158170
size_t size = 5;
159171

160-
backend_t backend = wasmfs_create_fetch_backend("small.dat",2);
172+
backend_t backend = wasmfs_create_fetch_backend("small.dat",2,NULL);
161173
int fd;
162174
char buf[size + 1];
163175
fd = wasmfs_create_file("/testfile4", 0777, backend);
@@ -203,7 +215,7 @@ void test_small_chunks_divisor_of_size() {
203215
char expected[] = "hello, fetch";
204216
size_t size = 12;
205217

206-
backend_t backend = wasmfs_create_fetch_backend("data.dat",4);
218+
backend_t backend = wasmfs_create_fetch_backend("data.dat",4,NULL);
207219
int fd;
208220
char buf[size + 1];
209221
fd = wasmfs_create_file("/testfile7", 0777, backend);
@@ -283,6 +295,7 @@ void test_nonexistent() {
283295
int main() {
284296
getUrlOrigin(url_orig, sizeof(url_orig));
285297
test_default();
298+
test_manifest();
286299
test_url_relative();
287300
test_url_absolute();
288301
test_directory_abs();

0 commit comments

Comments
 (0)