-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(iroh): add more rpc methods #1962
Changes from 2 commits
52bcaec
73592a3
c3abd8f
8799d7a
7a32e5f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,14 +56,15 @@ use crate::rpc_protocol::{ | |
BlobAddPathRequest, BlobAddPathResponse, BlobAddStreamRequest, BlobAddStreamResponse, | ||
BlobAddStreamUpdate, BlobDeleteBlobRequest, BlobDownloadRequest, BlobListCollectionsRequest, | ||
BlobListCollectionsResponse, BlobListIncompleteRequest, BlobListIncompleteResponse, | ||
BlobListRequest, BlobListResponse, BlobReadRequest, BlobReadResponse, BlobValidateRequest, | ||
CreateCollectionRequest, CreateCollectionResponse, DeleteTagRequest, DocExportFileRequest, | ||
DocExportFileResponse, DocExportProgress, DocImportFileRequest, DocImportFileResponse, | ||
DocImportProgress, DocSetHashRequest, DownloadLocation, ListTagsRequest, ListTagsResponse, | ||
NodeConnectionInfoRequest, NodeConnectionInfoResponse, NodeConnectionsRequest, | ||
NodeConnectionsResponse, NodeShutdownRequest, NodeStatsRequest, NodeStatsResponse, | ||
NodeStatusRequest, NodeStatusResponse, NodeWatchRequest, NodeWatchResponse, ProviderRequest, | ||
ProviderResponse, ProviderService, SetTagOption, | ||
BlobListRequest, BlobListResponse, BlobReadAtRequest, BlobReadAtResponse, BlobReadRequest, | ||
BlobReadResponse, BlobValidateRequest, CreateCollectionRequest, CreateCollectionResponse, | ||
DeleteTagRequest, DocExportFileRequest, DocExportFileResponse, DocExportProgress, | ||
DocImportFileRequest, DocImportFileResponse, DocImportProgress, DocSetHashRequest, | ||
DownloadLocation, ListTagsRequest, ListTagsResponse, NodeConnectionInfoRequest, | ||
NodeConnectionInfoResponse, NodeConnectionsRequest, NodeConnectionsResponse, | ||
NodeShutdownRequest, NodeStatsRequest, NodeStatsResponse, NodeStatusRequest, | ||
NodeStatusResponse, NodeWatchRequest, NodeWatchResponse, ProviderRequest, ProviderResponse, | ||
ProviderService, SetTagOption, | ||
}; | ||
use crate::sync_engine::{SyncEngine, SYNC_ALPN}; | ||
use crate::ticket::BlobTicket; | ||
|
@@ -1480,6 +1481,79 @@ impl<D: BaoStore> RpcHandler<D> { | |
rx.into_stream() | ||
} | ||
|
||
fn blob_read_at( | ||
self, | ||
req: BlobReadAtRequest, | ||
) -> impl Stream<Item = RpcResult<BlobReadAtResponse>> + Send + 'static { | ||
let (tx, rx) = flume::bounded(RPC_BLOB_GET_CHANNEL_CAP); | ||
let entry = self.inner.db.get(&req.hash); | ||
self.inner.rt.spawn_pinned(move || async move { | ||
if let Err(err) = read_loop( | ||
req.offset, | ||
req.len, | ||
entry, | ||
tx.clone(), | ||
RPC_BLOB_GET_CHUNK_SIZE, | ||
) | ||
.await | ||
{ | ||
tx.send_async(RpcResult::Err(err.into())).await.ok(); | ||
} | ||
}); | ||
|
||
async fn read_loop<M: Map>( | ||
offset: u64, | ||
len: Option<usize>, | ||
entry: Option<impl MapEntry<M>>, | ||
tx: flume::Sender<RpcResult<BlobReadAtResponse>>, | ||
max_chunk_size: usize, | ||
rklaehn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) -> anyhow::Result<()> { | ||
let entry = entry.ok_or_else(|| anyhow!("Blob not found"))?; | ||
let size = entry.size(); | ||
tx.send_async(Ok(BlobReadAtResponse::Entry { | ||
size, | ||
is_complete: entry.is_complete(), | ||
})) | ||
.await?; | ||
let mut reader = entry.data_reader().await?; | ||
|
||
let len = len.unwrap_or_else(|| (size - offset) as usize); | ||
|
||
let (num_chunks, chunk_size) = if len <= max_chunk_size { | ||
(1, len) | ||
} else { | ||
( | ||
(len as f64 / max_chunk_size as f64).ceil() as usize, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. weird to use f64 here... It is shorter than the integer variant, but will fail if len or max_chunk_size is > 2^53. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how would I round up otherwise? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. len / max_chunk_size + if len % max_chunk_size == 0 { 0 } else { 1 } or len / max_chunk_size + (len % max_chunk_size !=0) as usize or something. With a bit of luck the optimizer will do only 1 integer division for both division and rest. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that I don't worry about speed here. It's just weird to use fp for integer ops, and it will fail in weird ways as soon as you exceed the range of integers that can be losslessly represented in a fp num. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah yes, that is of course nice |
||
max_chunk_size, | ||
) | ||
}; | ||
|
||
let mut read = 0u64; | ||
for i in 0..num_chunks { | ||
let chunk_size = if i == num_chunks - 1 { | ||
// last chunk might be smaller | ||
len - read as usize | ||
} else { | ||
chunk_size | ||
}; | ||
let chunk = reader.read_at(offset + read, chunk_size).await?; | ||
let chunk_len = chunk.len(); | ||
if !chunk.is_empty() { | ||
tx.send_async(Ok(BlobReadAtResponse::Data { chunk })) | ||
.await?; | ||
} | ||
if chunk_len < chunk_size { | ||
break; | ||
} else { | ||
read += chunk_len as u64; | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
rx.into_stream() | ||
} | ||
|
||
fn node_connections( | ||
self, | ||
_: NodeConnectionsRequest, | ||
|
@@ -1605,6 +1679,10 @@ fn handle_rpc_request<D: BaoStore, E: ServiceEndpoint<ProviderService>>( | |
chan.server_streaming(msg, handler, RpcHandler::blob_read) | ||
.await | ||
} | ||
BlobReadAt(msg) => { | ||
chan.server_streaming(msg, handler, RpcHandler::blob_read_at) | ||
.await | ||
} | ||
BlobAddStream(msg) => { | ||
chan.bidi_streaming(msg, handler, RpcHandler::blob_add_stream) | ||
.await | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import section seems to indicate that wildcard imports aren't that bad after all....