prototype resumable send & recv
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type ResumeTransferErrorReason"; DO NOT EDIT.
|
||||
|
||||
package rpc
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _ResumeTransferErrorReason_name = "ResumeTransferErrorReasonNotImplementedResumeTransferErrorReasonDisabledResumeTransferErrorReasonZFSErrorPermanentResumeTransferErrorReasonZFSErrorMaybeTemporary"
|
||||
|
||||
var _ResumeTransferErrorReason_index = [...]uint8{0, 39, 72, 114, 161}
|
||||
|
||||
func (i ResumeTransferErrorReason) String() string {
|
||||
if i >= ResumeTransferErrorReason(len(_ResumeTransferErrorReason_index)-1) {
|
||||
return fmt.Sprintf("ResumeTransferErrorReason(%d)", i)
|
||||
}
|
||||
return _ResumeTransferErrorReason_name[_ResumeTransferErrorReason_index[i]:_ResumeTransferErrorReason_index[i+1]]
|
||||
}
|
||||
+47
@@ -17,6 +17,7 @@ type RPCRequester interface {
|
||||
FilesystemVersionsRequest(r FilesystemVersionsRequest) (versions []zfs.FilesystemVersion, err error)
|
||||
InitialTransferRequest(r InitialTransferRequest) (io.Reader, error)
|
||||
IncrementalTransferRequest(r IncrementalTransferRequest) (io.Reader, error)
|
||||
ResumeTransferRequest(r ResumeTransferRequest) (io.Reader, error)
|
||||
PullMeRequest(r PullMeRequest, handler RPCHandler) (err error)
|
||||
CloseRequest(r CloseRequest) (err error)
|
||||
ForceClose() (err error)
|
||||
@@ -30,6 +31,7 @@ type RPCHandler interface {
|
||||
|
||||
HandleInitialTransferRequest(r InitialTransferRequest) (io.Reader, error)
|
||||
HandleIncrementalTransferRequest(r IncrementalTransferRequest) (io.Reader, error)
|
||||
HandleResumeTransferRequest(r ResumeTransferRequest) (io.Reader, error)
|
||||
|
||||
// invert roles, i.e. handler becomes server and performs the requested pull using the client connection
|
||||
HandlePullMeRequest(r PullMeRequest, clientIdentity string, client RPCRequester) (err error)
|
||||
@@ -284,6 +286,37 @@ func (c ByteStreamRPC) serverLoop(handler RPCHandler) error {
|
||||
log.Printf("finished sending incremental snapshot stream: total %v bytes sent", watcher.Progress().TotalRX)
|
||||
}
|
||||
|
||||
case RTResumeTransferRequest:
|
||||
|
||||
var rq ResumeTransferRequest
|
||||
if err := recv(&rq); err != nil {
|
||||
sendError(EDecodeRequestBody, "")
|
||||
return conn.Close()
|
||||
}
|
||||
|
||||
stream, err := handler.HandleResumeTransferRequest(rq)
|
||||
if err != nil {
|
||||
sendError(EHandler, err.Error())
|
||||
} else {
|
||||
r := ResponseHeader{
|
||||
RequestId: header.Id,
|
||||
ResponseType: RChunkedStream,
|
||||
}
|
||||
send(&r)
|
||||
|
||||
chunker := NewChunker(stream)
|
||||
|
||||
watcher := IOProgressWatcher{Reader: &chunker}
|
||||
watcher.KickOff(1*time.Second, func(p IOProgress) {
|
||||
log.Printf("progress sending resumed stream: %v bytes sent", p.TotalRX)
|
||||
})
|
||||
_, err := io.Copy(conn, &watcher)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Printf("finished sending resumed stream: total %v bytes sent", watcher.Progress().TotalRX)
|
||||
}
|
||||
|
||||
case RTPullMeRequest:
|
||||
|
||||
var rq PullMeRequest
|
||||
@@ -375,6 +408,8 @@ func inferRequestType(v interface{}) (RequestType, error) {
|
||||
return RTInitialTransferRequest, nil
|
||||
case IncrementalTransferRequest:
|
||||
return RTIncrementalTransferRequest, nil
|
||||
case ResumeTransferRequest:
|
||||
return RTResumeTransferRequest, nil
|
||||
case PullMeRequest:
|
||||
return RTPullMeRequest, nil
|
||||
case CloseRequest:
|
||||
@@ -491,6 +526,14 @@ func (c ByteStreamRPC) IncrementalTransferRequest(r IncrementalTransferRequest)
|
||||
return
|
||||
}
|
||||
|
||||
func (c ByteStreamRPC) ResumeTransferRequest(r ResumeTransferRequest) (io.Reader, error) {
|
||||
// TODO reconstruct ResumeTransferError
|
||||
if err := c.sendRequestReceiveHeader(r, RChunkedStream); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewUnchunker(c.conn), nil
|
||||
}
|
||||
|
||||
func (c ByteStreamRPC) PullMeRequest(r PullMeRequest, handler RPCHandler) (err error) {
|
||||
err = c.sendRequestReceiveHeader(r, ROK)
|
||||
return c.serverLoop(handler)
|
||||
@@ -533,6 +576,10 @@ func (c LocalRPC) IncrementalTransferRequest(r IncrementalTransferRequest) (read
|
||||
return
|
||||
}
|
||||
|
||||
func (c LocalRPC) ResumeTransferRequest(r ResumeTransferRequest) (io.Reader, error) {
|
||||
return c.handler.HandleResumeTransferRequest(r)
|
||||
}
|
||||
|
||||
func (c LocalRPC) PullMeRequest(r PullMeRequest, handler RPCHandler) (err error) {
|
||||
// The config syntactically only allows local Pulls, hence this is never called
|
||||
// In theory, the following line should work:
|
||||
|
||||
@@ -19,6 +19,7 @@ const (
|
||||
RTFilesystemVersionsRequest = 0x11
|
||||
RTInitialTransferRequest = 0x12
|
||||
RTIncrementalTransferRequest = 0x13
|
||||
RTResumeTransferRequest = 0x14
|
||||
RTPullMeRequest = 0x20
|
||||
RTCloseRequest = 0xf0
|
||||
)
|
||||
@@ -51,6 +52,30 @@ type IncrementalTransferRequest struct {
|
||||
To zfs.FilesystemVersion
|
||||
}
|
||||
|
||||
type ResumeTransferRequest struct {
|
||||
Filesystem *zfs.DatasetPath
|
||||
Token string
|
||||
}
|
||||
|
||||
type ResumeTransferError struct {
|
||||
Reason ResumeTransferErrorReason
|
||||
ZFSError string
|
||||
}
|
||||
|
||||
func (e *ResumeTransferError) Error() string {
|
||||
return e.Reason.String()
|
||||
}
|
||||
|
||||
//go:generate stringer -type ResumeTransferErrorReason
|
||||
type ResumeTransferErrorReason uint8
|
||||
|
||||
const (
|
||||
ResumeTransferErrorReasonNotImplemented ResumeTransferErrorReason = iota
|
||||
ResumeTransferErrorReasonDisabled
|
||||
ResumeTransferErrorReasonZFSErrorPermanent
|
||||
ResumeTransferErrorReasonZFSErrorMaybeTemporary
|
||||
)
|
||||
|
||||
func (r IncrementalTransferRequest) Respond(snapshotReader io.Reader) {
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user