Skip to content

Commit 2b735d1

Browse files
authored
Merge pull request emscripten-core#21 from rstz/remove-sfa-support
Removed Storage Foundation Support, Simplify file packager code
2 parents 90e6d05 + 1f0106f commit 2b735d1

File tree

13 files changed

+645
-1229
lines changed

13 files changed

+645
-1229
lines changed

pthreadfs/README.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ The Emscripten Pthread File System (PThreadFS) unlocks using (partly) asynchrono
55
PThreadFS works by replacing Emscripten's file system API with a new API that proxies all file system operations to a dedicated pthread. This dedicated thread maintains a virtual file system that can use different APIs as backend (very similar to the way Emscripten's VFS is designed). In particular, PThreadFS comes with built-in support for asynchronous backends such as [OPFS Access Handles](https://docs.google.com/document/d/121OZpRk7bKSF7qU3kQLqAEUVSNxqREnE98malHYwWec/edit#heading=h.gj2fudnvy982).
66
Although the underlying storage API is asynchronous, PThreadFS makes it appear synchronous to the C++ application.
77

8-
If OPFS Access Handles are not available, PThreadFS will attempt to use the [Storage Foundation API](https://github.com/WICG/storage-foundation-api-explainer). As a last fallback, Emscripten's MEMFS in-memory file system is used.
8+
If OPFS Access Handles are not available, PThreadFS will use an in-memory file system.
99

1010
The code is still prototype quality and **should not be used in a production environment** for the time being.
1111

1212
## Enable OPFS Access Handles in Chrome
1313

14-
OPFS Access Handles require recent versions of Google Chrome Canary. "Experimental Web Platform Features" must be enabled in [chrome://flags](chrome://flags).
14+
OPFS Access Handles require Google Chrome 96. "Experimental Web Platform Features" must be enabled in [chrome://flags](chrome://flags).
1515

1616
Alternatively, you may enable the API with Chrome's " --enable-runtime-features=FileSystemAccessAccessHandle". On MacOS, this can be done through
1717
```
1818
open -a /Applications/Google\ Chrome\ Canary.app --args --enable-runtime-features=FileSystemAccessAccessHandle
1919
```
2020

21-
Both Storage Foundation API and OPFS are available as [origin trials](https://developer.chrome.com/origintrials/) in Chrome 95.
21+
OPFS Access Handles are available as [origin trial](https://developer.chrome.com/origintrials/) in Chrome 95.
2222
## Getting the code
2323

2424
PthreadFS is available on Github in the [emscripten-pthreadfs](https://github.com/rstz/emscripten-pthreadfs) repository. All code resides in the `pthreadfs` folder. It should be usable with any up-to-date Emscripten version.
@@ -74,7 +74,6 @@ See `pthreadfs/examples/emscripten-tests/fsafs.cpp` for exemplary usage.
7474
- PThreadFS depends on C++ libraries. `EM_PTHREADFS_ASM()` cannot be used within C files.
7575
- Performance is good if and only if optimizations (compiler option `-O2`) are enabled and DevTools are closed.
7676
- Accessing the file system before `main()` requires linker option `PTHREAD_POOL_SIZE=<expression>` to be active. Doing so may lead to some blocking of the main thread, which is risky. Check out `examples/early_syscall.cpp` for an example.
77-
- The Storage Foundation backend requires case-insensitive file names.
7877
- Compiling with the Closure Compiler is not supported.
7978
- Compiling with optimization `-O3` is not yet supported and may lead to a faulty build.
8079

@@ -98,23 +97,23 @@ python3 -m http.server 8888
9897
Then open the following link in a Chrome instance with the
9998
_OPFS Access Handles_ [enabled](#enable-and-detect-opfs-in-chrome):
10099

101-
[localhost:8888/sqlite-speedtest](http://localhost:8888/sqlite-speedtest). The results of the speedtest can be found in the DevTools console.
100+
[localhost:8888/sqlite-speedtest](http://localhost:8888/sqlite-speedtest).
102101

103102
### Other tests
104103

105-
The folder `pthreadfs/examples/emscripten-tests` contains a number of other file system tests, mostly taken from Emscripten's standard test suite.
104+
The folder `pthreadfs/examples/` contains a number of other tests.
106105

107106
To compile, navigate to the `pthreadfs/examples/` directory and run
108107

109108
```shell
110-
make emscripten-tests
111-
cd dist/emscripten-tests
109+
make all
110+
cd dist/
112111
python3 -m http.server 8888
113112
```
114113
Then open the following link in a Chrome instance with the
115114
_OPFS Access Handles_ [enabled](#enable-and-detect-opfs-in-chrome):
116115

117-
[localhost:8888/emscripten-tests](http://localhost:8888/emscripten-tests) and choose a test. The results of the test can be found in the DevTools console.
116+
[localhost:8888](http://localhost:8888) and choose a test. The results of the test can be found in the DevTools console.
118117

119118
## Authors
120119
- Richard Stotz (<[email protected]>)

pthreadfs/examples/Makefile

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ SQLITE_SPEEDTEST_URL = https://sqlite.org/src/raw/5e5b805f24cc939656058f6a498f5a
2828
SQLITE_SPEEDTEST_SHA1 = f0edde2ad68f090e4676ac30042e0f6b765a8528
2929

3030
.PHONY: all
31-
all: sqlite-speedtest emscripten-tests packager-tests
31+
all: sqlite-speedtest emscripten-tests packager-tests jsops-tests
3232

3333
## cache
3434
cache/$(SQLITE_AMALGAMATION).zip:
@@ -179,4 +179,20 @@ dist/$(PACKAGERTESTS)/preloading.html: $(OBJ)/preloading.o $(OBJ)/pthreadfs.o di
179179

180180
dist/$(PACKAGERTESTS)/intermediate_loading.html: $(OBJ)/intermediate_loading.o $(OBJ)/pthreadfs.o dist/$(PACKAGERTESTS)/pkg_intermediate_small.js dist/$(PACKAGERTESTS)/pkg_intermediate_mediumlarge.js $(PTHREADFS_JS)
181181
mkdir -p dist/$(PACKAGERTESTS)
182-
$(EMCC) $(LINK_FLAGS) -o $@ --js-library=$(PTHREADFS_JS) $< $(word 2,$^)
182+
$(EMCC) $(LINK_FLAGS) -o $@ --js-library=$(PTHREADFS_JS) $< $(word 2,$^)
183+
184+
JSOPSTESTS = jsops-tests
185+
.PHONY: jsops-tests
186+
jsops-tests: dist/$(JSOPSTESTS)/write_from_main_thread.html dist/$(JSOPSTESTS)/read_from_main_thread.html
187+
188+
$(OBJ)/%.o : $(JSOPSTESTS)/%.cpp
189+
mkdir -p $(OBJ)
190+
$(EMCC) -c $(CFLAGS) $< -o $@
191+
192+
dist/$(JSOPSTESTS)/write_from_main_thread.html: $(OBJ)/write_from_main_thread.o $(OBJ)/pthreadfs.o $(JSOPSTESTS)/write_from_main_thread_pre.js $(PTHREADFS_JS)
193+
mkdir -p dist/$(JSOPSTESTS)
194+
$(EMCC) $(LINK_FLAGS) -o $@ --js-library=$(PTHREADFS_JS) --pre-js $(word 3,$^) $< $(word 2,$^)
195+
196+
dist/$(JSOPSTESTS)/read_from_main_thread.html: $(OBJ)/read_from_main_thread.o $(OBJ)/pthreadfs.o $(PTHREADFS_JS)
197+
mkdir -p dist/$(JSOPSTESTS)
198+
$(EMCC) $(LINK_FLAGS) -o $@ --js-library=$(PTHREADFS_JS) $< $(word 2,$^)

pthreadfs/examples/emscripten-tests/stat.cpp

Lines changed: 9 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,37 @@
1313
#include <stdio.h>
1414
#include <stdlib.h>
1515
#include <string.h>
16+
#include <sys/stat.h>
17+
#include <sys/sysmacros.h>
18+
#include <sys/types.h>
1619
#include <time.h>
1720
#include <unistd.h>
1821
#include <utime.h>
19-
#include <sys/stat.h>
20-
#include <sys/types.h>
21-
#include <sys/sysmacros.h>
2222

23-
void create_file(const char *path, const char *buffer, int mode) {
23+
void create_file(const char* path, const char* buffer, int mode) {
2424
int fd = open(path, O_CREAT | O_TRUNC | O_RDWR, mode);
2525
assert(fd >= 0);
2626

2727
int err = write(fd, buffer, sizeof(char) * strlen(buffer));
28-
assert(err == (sizeof(char) * strlen(buffer)));
28+
assert(err == (sizeof(char) * strlen(buffer)));
2929

3030
close(fd);
3131
}
3232

3333
void setup() {
34-
// struct utimbuf t = {1200000000, 1200000000};
35-
3634
mkdir("persistent/folder", 0777);
3735
create_file("persistent/folder/file", "abcdef", 0777);
38-
//symlink("file", "folder/file-link");
39-
40-
//utime("folder/file", &t);
41-
//utime("folder", &t);
4236
}
4337

4438
void cleanup() {
4539
rmdir("persistent/folder/subdir");
4640
unlink("persistent/folder/file");
47-
// unlink("folder/file-link");
4841
rmdir("persistent/folder");
4942
}
5043

5144
void test() {
5245
int err;
5346
struct stat s;
54-
// struct utimbuf t = {1200000000, 1200000000};
5547

5648
// non-existent
5749
err = stat("persistent/does_not_exist", &s);
@@ -110,7 +102,8 @@ void test() {
110102

111103
// fstat a file (should match file stat from above)
112104
memset(&s, 0, sizeof(s));
113-
err = fstat(open("persistent/folder/file", O_RDONLY), &s);
105+
int fd = open("persistent/folder/file", O_RDONLY);
106+
err = fstat(fd, &s);
114107
assert(!err);
115108
assert(s.st_dev);
116109
assert(s.st_ino);
@@ -125,6 +118,8 @@ void test() {
125118
assert(s.st_blksize == 4096);
126119
assert(s.st_blocks == 1);
127120
#endif
121+
err = close(fd);
122+
assert(!err);
128123

129124
// stat a device
130125
memset(&s, 0, sizeof(s));
@@ -146,54 +141,6 @@ void test() {
146141
assert(s.st_blksize == 4096);
147142
assert(s.st_blocks == 0);
148143
#endif
149-
150-
// stat a link (should match the file stat from above)
151-
// memset(&s, 0, sizeof(s));
152-
// err = stat("folder/file-link", &s);
153-
// assert(!err);
154-
// assert(s.st_dev);
155-
// assert(s.st_ino);
156-
// assert(S_ISREG(s.st_mode));
157-
// assert(s.st_nlink);
158-
// assert(s.st_rdev == 0);
159-
// assert(s.st_size == 6);
160-
// assert(s.st_atime == 1200000000);
161-
// assert(s.st_mtime == 1200000000);
162-
// assert(s.st_ctime);
163-
// #ifdef __EMSCRIPTEN__
164-
// assert(s.st_blksize == 4096);
165-
// assert(s.st_blocks == 1);
166-
// #endif
167-
168-
// lstat a link (should NOT match the file stat from above)
169-
// memset(&s, 0, sizeof(s));
170-
// err = lstat("folder/file-link", &s);
171-
// assert(!err);
172-
// assert(s.st_dev);
173-
// assert(s.st_ino);
174-
// assert(S_ISLNK(s.st_mode));
175-
// assert(s.st_nlink);
176-
// assert(s.st_rdev == 0);
177-
// assert(s.st_size == 4); // strlen("file")
178-
// assert(s.st_atime != 1200000000); // should NOT match the utime call we did for dir/file
179-
// assert(s.st_mtime != 1200000000);
180-
// assert(s.st_ctime);
181-
// #ifdef __EMSCRIPTEN__
182-
// assert(s.st_blksize == 4096);
183-
// assert(s.st_blocks == 1);
184-
// #endif
185-
186-
// create and unlink files inside a directory and check that mtime updates
187-
mkdir("persistent/folder/subdir", 0777);
188-
// utime("persistent/folder/subdir", &t);
189-
create_file("persistent/folder/subdir/file", "abcdef", 0777);
190-
err = stat("persistent/folder/subdir", &s);
191-
// assert(s.st_mtime != 1200000000);
192-
// utime("persistent/folder/subdir", &t);
193-
unlink("persistent/folder/subdir/file");
194-
err = stat("persistent/folder/subdir", &s);
195-
// assert(s.st_mtime != 1200000000);
196-
197144
puts("success");
198145
}
199146

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2013 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <assert.h>
9+
#include <ctype.h>
10+
#include <dirent.h>
11+
#include <errno.h>
12+
#include <fcntl.h>
13+
#include <signal.h>
14+
#include <stdio.h>
15+
#include <stdlib.h>
16+
#include <string.h>
17+
#include <unistd.h>
18+
19+
#include "emscripten.h"
20+
21+
void create_file(const char* path, const char* contents, int mode) {
22+
int fd = open(path, O_CREAT | O_TRUNC | O_RDWR, mode);
23+
assert(fd >= 0);
24+
25+
int err = write(fd, contents, sizeof(char) * strlen(contents));
26+
assert(err == (sizeof(char) * strlen(contents)));
27+
28+
close(fd);
29+
}
30+
31+
void test_file_contents(const char* path, const char* contents) {
32+
MAIN_THREAD_ASYNC_EM_ASM({
33+
(async() => {
34+
let path = UTF8ToString($0);
35+
await PThreadFS.init("persistent");
36+
let content = await PThreadFS.readFile(path);
37+
content = new TextDecoder().decode(content);
38+
if (content != UTF8ToString($1)) {
39+
throw new Error('Incorrect contents read: ' + content);
40+
}
41+
await PThreadFS.unlink(path);
42+
console.log("Success");
43+
})();
44+
}, path, contents);
45+
}
46+
47+
int main() {
48+
const char* path = "persistent/read_from_main_file.txt";
49+
const char* contents = "file_contents :)";
50+
create_file(path, contents, 0777);
51+
52+
test_file_contents(path, contents);
53+
54+
puts("Check the console for success");
55+
return EXIT_SUCCESS;
56+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2013 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <assert.h>
9+
#include <ctype.h>
10+
#include <dirent.h>
11+
#include <errno.h>
12+
#include <fcntl.h>
13+
#include <signal.h>
14+
#include <stdio.h>
15+
#include <stdlib.h>
16+
#include <string.h>
17+
#include <sys/stat.h>
18+
#include <unistd.h>
19+
20+
void cleanup() {
21+
rmdir("persistent/mainthreadfolder/subfolder");
22+
rmdir("persistent/mainthreadfolder");
23+
}
24+
25+
void test_file_contents(const char* path) {
26+
printf("Test contents for file %s\n", path);
27+
28+
int fd = open(path, O_RDONLY, 0777);
29+
assert(fd >= 0);
30+
31+
char readbuf[1000];
32+
int bytes_read = read(fd, readbuf, sizeof(char) * (strlen(path) + 20));
33+
assert(bytes_read > 0);
34+
printf("Content: %s\n", readbuf);
35+
close(fd);
36+
37+
unlink(path);
38+
}
39+
40+
int main() {
41+
const char* paths[] = {"persistent/file.txt", "persistent/mainthreadfolder/subfolder/ok now"};
42+
43+
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
44+
test_file_contents(paths[i]);
45+
}
46+
cleanup();
47+
48+
puts("success");
49+
return EXIT_SUCCESS;
50+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
if ("preRun" in Module) {
2+
Module["preRun"].push(async () => {
3+
await PThreadFS.init('persistent');
4+
await PThreadFS.writeFile("persistent/file.txt", "the contents of persistent/file.txt !!", {});
5+
await PThreadFS.createPath("/", "persistent/mainthreadfolder/subfolder/", true, true);
6+
await PThreadFS.writeFile("persistent/mainthreadfolder/subfolder/ok now",
7+
"the contents of persistent/mainthreadfolder/subfolder/ok now !!", {});
8+
});
9+
}

0 commit comments

Comments
 (0)