0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

Rename FdTable to ResourceTable.

Add docs to src/resources.rs.
This commit is contained in:
Ryan Dahl 2018-10-01 19:37:18 -04:00
parent 393f751a27
commit 42c5b103ec
6 changed files with 146 additions and 139 deletions

View file

@ -47,7 +47,7 @@ export async function open(
assert(fbs.Any.OpenRes === baseRes!.msgType());
const res = new fbs.OpenRes();
assert(baseRes!.msg(res) != null);
const fd = res.fd();
const fd = res.rid();
return new File(fd);
}
@ -57,7 +57,7 @@ export async function read(
): Promise<ReadResult> {
const builder = new flatbuffers.Builder();
fbs.Read.startRead(builder);
fbs.Read.addFd(builder, fd);
fbs.Read.addRid(builder, fd);
const msg = fbs.Read.endRead(builder);
const baseRes = await dispatch.sendAsync(builder, fbs.Any.Read, msg, p);
assert(baseRes != null);
@ -70,7 +70,7 @@ export async function read(
export async function write(fd: number, p: ArrayBufferView): Promise<number> {
const builder = new flatbuffers.Builder();
fbs.Write.startWrite(builder);
fbs.Write.addFd(builder, fd);
fbs.Write.addRid(builder, fd);
const msg = fbs.Write.endWrite(builder);
const baseRes = await dispatch.sendAsync(builder, fbs.Any.Write, msg, p);
assert(baseRes != null);
@ -83,7 +83,7 @@ export async function write(fd: number, p: ArrayBufferView): Promise<number> {
export function close(fd: number): void {
const builder = new flatbuffers.Builder();
fbs.Close.startClose(builder);
fbs.Close.addFd(builder, fd);
fbs.Close.addRid(builder, fd);
const msg = fbs.Close.endClose(builder);
dispatch.sendSync(builder, fbs.Any.Close, msg);
}

View file

@ -1,119 +0,0 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
use futures;
use futures::Poll;
use std;
use std::collections::HashMap;
use std::io::Error;
use std::io::{Read, Write};
use std::sync::atomic::AtomicIsize;
use std::sync::atomic::Ordering;
use std::sync::Mutex;
use tokio;
use tokio::io::{AsyncRead, AsyncWrite};
// These store Deno's file descriptors. These are not necessarally the operating
// system ones.
type FdTable = HashMap<i32, Repr>;
lazy_static! {
// Starts at 3 because stdio is [0-2].
static ref NEXT_FD: AtomicIsize = AtomicIsize::new(3);
static ref FD_TABLE: Mutex<FdTable> = Mutex::new({
let mut m = HashMap::new();
// TODO Load these lazily during lookup?
m.insert(0, Repr::Stdin(tokio::io::stdin()));
m.insert(1, Repr::Stdout(tokio::io::stdout()));
m.insert(2, Repr::Stderr(tokio::io::stderr()));
m
});
}
// Internal representation of DFile.
enum Repr {
Stdin(tokio::io::Stdin),
Stdout(tokio::io::Stdout),
Stderr(tokio::io::Stderr),
FsFile(tokio::fs::File),
}
// Abstract async file interface.
// fd does not necessarally correspond to an OS fd.
// Ideally in unix, if DFile represents an OS fd, it will be the same.
pub struct DFile {
pub fd: i32,
}
impl Read for DFile {
fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
unimplemented!();
}
}
impl AsyncRead for DFile {
fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, Error> {
let mut table = FD_TABLE.lock().unwrap();
let maybe_repr = table.get_mut(&self.fd);
match maybe_repr {
None => panic!("bad fd"),
Some(repr) => match repr {
Repr::FsFile(ref mut f) => f.poll_read(buf),
Repr::Stdin(ref mut f) => f.poll_read(buf),
Repr::Stdout(_) | Repr::Stderr(_) => {
panic!("Cannot read from stdout/stderr")
}
},
}
}
}
impl Write for DFile {
fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
unimplemented!()
}
fn flush(&mut self) -> std::io::Result<()> {
unimplemented!()
}
}
impl AsyncWrite for DFile {
fn poll_write(&mut self, buf: &[u8]) -> Poll<usize, Error> {
let mut table = FD_TABLE.lock().unwrap();
let maybe_repr = table.get_mut(&self.fd);
match maybe_repr {
None => panic!("bad fd"),
Some(repr) => match repr {
Repr::FsFile(ref mut f) => f.poll_write(buf),
Repr::Stdout(ref mut f) => f.poll_write(buf),
Repr::Stderr(ref mut f) => f.poll_write(buf),
Repr::Stdin(_) => panic!("Cannot write to stdin"),
},
}
}
fn shutdown(&mut self) -> futures::Poll<(), std::io::Error> {
unimplemented!()
}
}
fn new_fd() -> i32 {
// TODO If on unix, just extract the real FD of fs_file.
// let fd = AsRawFd::as_raw_fd(fs_file.std());
let next_fd = NEXT_FD.fetch_add(1, Ordering::SeqCst);
next_fd as i32
}
pub fn add_fs_file(fs_file: tokio::fs::File) -> DFile {
let fd = new_fd();
let mut tg = FD_TABLE.lock().unwrap();
match tg.insert(fd, Repr::FsFile(fs_file)) {
Some(_) => panic!("There is already a file with that fd"),
None => DFile { fd },
}
}
pub fn lookup(fd: i32) -> Option<DFile> {
let table = FD_TABLE.lock().unwrap();
table.get(&fd).map(|_| DFile { fd })
}

View file

@ -9,7 +9,6 @@ use isolate::IsolateState;
use isolate::Op;
use msg;
use files;
use flatbuffers::FlatBufferBuilder;
use futures;
use futures::future::poll_fn;
@ -19,6 +18,7 @@ use hyper;
use hyper::rt::{Future, Stream};
use hyper::Client;
use remove_dir_all::remove_dir_all;
use resources;
use std;
use std::fs;
#[cfg(any(unix))]
@ -575,12 +575,12 @@ fn handle_open(
let op = tokio::fs::File::open(filename)
.map_err(|err| DenoError::from(err))
.and_then(move |fs_file| -> OpResult {
let dfile = files::add_fs_file(fs_file);
let resource = resources::add_fs_file(fs_file);
let builder = &mut FlatBufferBuilder::new();
let msg = msg::OpenRes::create(
builder,
&msg::OpenResArgs {
fd: dfile.fd,
rid: resource.rid,
..Default::default()
},
);
@ -604,16 +604,16 @@ fn handle_read(
) -> Box<Op> {
let cmd_id = base.cmd_id();
let msg = base.msg_as_read().unwrap();
let fd = msg.fd();
let rid = msg.rid();
match files::lookup(fd) {
match resources::lookup(rid) {
None => odd_future(errors::new(
errors::ErrorKind::BadFileDescriptor,
String::from("Bad File Descriptor"),
)),
Some(mut dfile) => {
Some(mut resource) => {
let op = futures::future::poll_fn(move || {
let poll = dfile.poll_read(data);
let poll = resource.poll_read(data);
poll
}).map_err(|err| DenoError::from(err))
.and_then(move |nread: usize| {
@ -648,16 +648,16 @@ fn handle_write(
) -> Box<Op> {
let cmd_id = base.cmd_id();
let msg = base.msg_as_write().unwrap();
let fd = msg.fd();
let rid = msg.rid();
match files::lookup(fd) {
match resources::lookup(rid) {
None => odd_future(errors::new(
errors::ErrorKind::BadFileDescriptor,
String::from("Bad File Descriptor"),
)),
Some(mut dfile) => {
Some(mut resource) => {
let op = futures::future::poll_fn(move || {
let poll = dfile.poll_write(data);
let poll = resource.poll_write(data);
poll
}).map_err(|err| DenoError::from(err))
.and_then(move |bytes_written: usize| {

View file

@ -23,13 +23,13 @@ extern crate ring;
mod deno_dir;
mod errors;
mod files;
mod flags;
mod fs;
pub mod handlers;
mod http;
mod isolate;
mod libdeno;
mod resources;
mod tokio_util;
mod version;

View file

@ -265,11 +265,11 @@ table Open {
}
table OpenRes {
fd: int;
rid: int;
}
table Read {
fd: int;
rid: int;
// (ptr, len) is passed as second parameter to libdeno.send().
}
@ -279,7 +279,7 @@ table ReadRes {
}
table Write {
fd: int;
rid: int;
}
table WriteRes {
@ -287,7 +287,7 @@ table WriteRes {
}
table Close {
fd: int;
rid: int;
}
root_type Base;

126
src/resources.rs Normal file
View file

@ -0,0 +1,126 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
// Think of Resources as File Descriptors. They are integers that are allocated
// by the privlaged side of Deno to refer to various resources. The simplest
// example are standard file system files and stdio - but there will be other
// resources added in the future that might not correspond to operating system
// level File Descriptors. To avoid confusion we call them "resources" not "file
// descriptors". This module implements a global resource table. Ops (AKA
// handlers) look up resources by their integer id here.
use futures;
use futures::Poll;
use std;
use std::collections::HashMap;
use std::io::Error;
use std::io::{Read, Write};
use std::sync::atomic::AtomicIsize;
use std::sync::atomic::Ordering;
use std::sync::Mutex;
use tokio;
use tokio::io::{AsyncRead, AsyncWrite};
pub type ResourceId = i32; // Sometimes referred to RID.
// These store Deno's file descriptors. These are not necessarily the operating
// system ones.
type ResourceTable = HashMap<ResourceId, Repr>;
lazy_static! {
// Starts at 3 because stdio is [0-2].
static ref NEXT_RID: AtomicIsize = AtomicIsize::new(3);
static ref RESOURCE_TABLE: Mutex<ResourceTable> = Mutex::new({
let mut m = HashMap::new();
// TODO Load these lazily during lookup?
m.insert(0, Repr::Stdin(tokio::io::stdin()));
m.insert(1, Repr::Stdout(tokio::io::stdout()));
m.insert(2, Repr::Stderr(tokio::io::stderr()));
m
});
}
// Internal representation of Resource.
enum Repr {
Stdin(tokio::io::Stdin),
Stdout(tokio::io::Stdout),
Stderr(tokio::io::Stderr),
FsFile(tokio::fs::File),
}
// Abstract async file interface.
// Ideally in unix, if Resource represents an OS rid, it will be the same.
pub struct Resource {
pub rid: ResourceId,
}
impl Read for Resource {
fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
unimplemented!();
}
}
impl AsyncRead for Resource {
fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, Error> {
let mut table = RESOURCE_TABLE.lock().unwrap();
let maybe_repr = table.get_mut(&self.rid);
match maybe_repr {
None => panic!("bad rid"),
Some(repr) => match repr {
Repr::FsFile(ref mut f) => f.poll_read(buf),
Repr::Stdin(ref mut f) => f.poll_read(buf),
Repr::Stdout(_) | Repr::Stderr(_) => {
panic!("Cannot read from stdout/stderr")
}
},
}
}
}
impl Write for Resource {
fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
unimplemented!()
}
fn flush(&mut self) -> std::io::Result<()> {
unimplemented!()
}
}
impl AsyncWrite for Resource {
fn poll_write(&mut self, buf: &[u8]) -> Poll<usize, Error> {
let mut table = RESOURCE_TABLE.lock().unwrap();
let maybe_repr = table.get_mut(&self.rid);
match maybe_repr {
None => panic!("bad rid"),
Some(repr) => match repr {
Repr::FsFile(ref mut f) => f.poll_write(buf),
Repr::Stdout(ref mut f) => f.poll_write(buf),
Repr::Stderr(ref mut f) => f.poll_write(buf),
Repr::Stdin(_) => panic!("Cannot write to stdin"),
},
}
}
fn shutdown(&mut self) -> futures::Poll<(), std::io::Error> {
unimplemented!()
}
}
fn new_rid() -> ResourceId {
let next_rid = NEXT_RID.fetch_add(1, Ordering::SeqCst);
next_rid as ResourceId
}
pub fn add_fs_file(fs_file: tokio::fs::File) -> Resource {
let rid = new_rid();
let mut tg = RESOURCE_TABLE.lock().unwrap();
match tg.insert(rid, Repr::FsFile(fs_file)) {
Some(_) => panic!("There is already a file with that rid"),
None => Resource { rid },
}
}
pub fn lookup(rid: ResourceId) -> Option<Resource> {
let table = RESOURCE_TABLE.lock().unwrap();
table.get(&rid).map(|_| Resource { rid })
}