diff options
author | Tilman Roeder <dyed.green.info@gmail.com> | 2021-08-24 14:21:31 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-24 15:21:31 +0200 |
commit | 93d83a84dbe1f6ecf93b596f88bc85ba378fa986 (patch) | |
tree | 8f9165f29064b0eb6d34661577877ebc2a3e37b3 /runtime | |
parent | 46e4ba38b2b1ccee8d3b4f04be1a2cc0b42cd52a (diff) |
feat(unstable): Add file locking APIs (#11746)
This commit adds following unstable APIs:
- Deno.flock()
- Deno.flockSync()
- Deno.funlock()
- Deno.funlockSync()
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/Cargo.toml | 1 | ||||
-rw-r--r-- | runtime/js/30_fs.js | 20 | ||||
-rw-r--r-- | runtime/js/90_deno_ns.js | 4 | ||||
-rw-r--r-- | runtime/ops/fs.rs | 118 |
4 files changed, 143 insertions, 0 deletions
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 491516dbb..520509450 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -65,6 +65,7 @@ atty = "0.2.14" dlopen = "0.1.8" encoding_rs = "0.8.28" filetime = "0.2.14" +fs3 = "0.5.0" http = "0.2.4" hyper = { version = "0.14.10", features = ["server", "stream", "http1", "http2", "runtime"] } # TODO(lucacasonato): unlock when https://github.com/tkaitchuck/aHash/issues/95 is resolved diff --git a/runtime/js/30_fs.js b/runtime/js/30_fs.js index e45cda321..feb9f8f54 100644 --- a/runtime/js/30_fs.js +++ b/runtime/js/30_fs.js @@ -385,6 +385,22 @@ await core.opAsync("op_fsync_async", rid); } + function flockSync(rid, exclusive) { + core.opSync("op_flock_sync", rid, exclusive === true); + } + + async function flock(rid, exclusive) { + await core.opAsync("op_flock_async", rid, exclusive === true); + } + + function funlockSync(rid) { + core.opSync("op_funlock_sync", rid); + } + + async function funlock(rid) { + await core.opAsync("op_funlock_async", rid); + } + window.__bootstrap.fs = { cwd, chdir, @@ -433,5 +449,9 @@ fdatasyncSync, fsync, fsyncSync, + flock, + flockSync, + funlock, + funlockSync, }; })(this); diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index 796361d7a..71c8bd0f0 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -136,5 +136,9 @@ createHttpClient: __bootstrap.fetch.createHttpClient, http: __bootstrap.http, dlopen: __bootstrap.ffi.dlopen, + flock: __bootstrap.fs.flock, + flockSync: __bootstrap.fs.flockSync, + funlock: __bootstrap.fs.funlock, + funlockSync: __bootstrap.fs.funlockSync, }; })(this); diff --git a/runtime/ops/fs.rs b/runtime/ops/fs.rs index 419e41718..819f3f3ac 100644 --- a/runtime/ops/fs.rs +++ b/runtime/ops/fs.rs @@ -48,6 +48,10 @@ pub fn init() -> Extension { ("op_fsync_async", op_async(op_fsync_async)), ("op_fstat_sync", op_sync(op_fstat_sync)), ("op_fstat_async", op_async(op_fstat_async)), + ("op_flock_sync", op_sync(op_flock_sync)), + ("op_flock_async", op_async(op_flock_async)), + ("op_funlock_sync", op_sync(op_funlock_sync)), + ("op_funlock_async", op_async(op_funlock_async)), ("op_umask", op_sync(op_umask)), ("op_chdir", op_sync(op_chdir)), ("op_mkdir_sync", op_sync(op_mkdir_sync)), @@ -346,6 +350,120 @@ async fn op_fstat_async( Ok(get_stat(metadata)) } +fn op_flock_sync( + state: &mut OpState, + rid: ResourceId, + exclusive: bool, +) -> Result<(), AnyError> { + use fs3::FileExt; + super::check_unstable(state, "Deno.flockSync"); + + StdFileResource::with(state, rid, |r| match r { + Ok(std_file) => { + if exclusive { + std_file.lock_exclusive()?; + } else { + std_file.lock_shared()?; + } + Ok(()) + } + Err(_) => Err(type_error("cannot lock this type of resource".to_string())), + }) +} + +async fn op_flock_async( + state: Rc<RefCell<OpState>>, + rid: ResourceId, + exclusive: bool, +) -> Result<(), AnyError> { + use fs3::FileExt; + super::check_unstable2(&state, "Deno.flock"); + + let resource = state + .borrow_mut() + .resource_table + .get::<StdFileResource>(rid)?; + + if resource.fs_file.is_none() { + return Err(bad_resource_id()); + } + + let mut fs_file = RcRef::map(&resource, |r| r.fs_file.as_ref().unwrap()) + .borrow_mut() + .await; + + let std_file = (*fs_file) + .0 + .as_mut() + .unwrap() + .try_clone() + .await? + .into_std() + .await; + tokio::task::spawn_blocking(move || -> Result<(), AnyError> { + if exclusive { + std_file.lock_exclusive()?; + } else { + std_file.lock_shared()?; + } + Ok(()) + }) + .await? +} + +fn op_funlock_sync( + state: &mut OpState, + rid: ResourceId, + _: (), +) -> Result<(), AnyError> { + use fs3::FileExt; + super::check_unstable(state, "Deno.funlockSync"); + + StdFileResource::with(state, rid, |r| match r { + Ok(std_file) => { + std_file.unlock()?; + Ok(()) + } + Err(_) => Err(type_error("cannot lock this type of resource".to_string())), + }) +} + +async fn op_funlock_async( + state: Rc<RefCell<OpState>>, + rid: ResourceId, + _: (), +) -> Result<(), AnyError> { + use fs3::FileExt; + super::check_unstable2(&state, "Deno.funlock"); + + let resource = state + .borrow_mut() + .resource_table + .get::<StdFileResource>(rid)?; + + if resource.fs_file.is_none() { + return Err(bad_resource_id()); + } + + let mut fs_file = RcRef::map(&resource, |r| r.fs_file.as_ref().unwrap()) + .borrow_mut() + .await; + + let std_file = (*fs_file) + .0 + .as_mut() + .unwrap() + .try_clone() + .await? + .into_std() + .await; + tokio::task::spawn_blocking(move || -> Result<(), AnyError> { + std_file.unlock()?; + Ok(()) + }) + .await? +} + fn op_umask( state: &mut OpState, mask: Option<u32>, |