rpc: Re-factor ReadFile behavior client <--> server.

Current code did not marshal/unmarshal buffers properly from
the server, The reason being buffers have to be allocated and
sent properly back to client to be consumable.
This commit is contained in:
Harshavardhana 2016-08-11 19:32:04 -07:00
parent 6908a0dcd4
commit 43098df9d8
3 changed files with 34 additions and 14 deletions

View file

@ -49,6 +49,9 @@ func splitNetPath(networkPath string) (netAddr, netPath string) {
// written so that the storageAPI errors are consistent across network // written so that the storageAPI errors are consistent across network
// disks as well. // disks as well.
func toStorageErr(err error) error { func toStorageErr(err error) error {
if err == nil {
return nil
}
switch err.Error() { switch err.Error() {
case io.EOF.Error(): case io.EOF.Error():
return io.EOF return io.EOF
@ -240,16 +243,18 @@ func (n networkStorage) ReadFile(volume string, path string, offset int64, buffe
if n.rpcClient == nil { if n.rpcClient == nil {
return 0, errVolumeBusy return 0, errVolumeBusy
} }
if err = n.rpcClient.Call("Storage.ReadFileHandler", ReadFileArgs{ var result []byte
err = n.rpcClient.Call("Storage.ReadFileHandler", ReadFileArgs{
Token: n.rpcToken, Token: n.rpcToken,
Vol: volume, Vol: volume,
Path: path, Path: path,
Offset: offset, Offset: offset,
Buffer: buffer, Size: len(buffer),
}, &m); err != nil { }, &result)
return 0, toStorageErr(err) // Copy results to buffer.
} copy(buffer, result)
return m, nil // Return length of result, err if any.
return int64(len(result)), toStorageErr(err)
} }
// ListDir - list all entries at prefix. // ListDir - list all entries at prefix.

View file

@ -76,8 +76,8 @@ type ReadFileArgs struct {
// Starting offset to start reading into Buffer. // Starting offset to start reading into Buffer.
Offset int64 Offset int64
// Data buffer read from the path at offset. // Data size read from the path at offset.
Buffer []byte Size int
} }
// AppendFileArgs represents append file RPC arguments. // AppendFileArgs represents append file RPC arguments.

View file

@ -17,8 +17,10 @@
package main package main
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"io"
"net/rpc" "net/rpc"
"path" "path"
"strings" "strings"
@ -162,16 +164,29 @@ func (s *storageServer) ReadAllHandler(args *ReadFileArgs, reply *[]byte) error
} }
// ReadFileHandler - read file handler is rpc wrapper to read file. // ReadFileHandler - read file handler is rpc wrapper to read file.
func (s *storageServer) ReadFileHandler(args *ReadFileArgs, reply *int64) error { func (s *storageServer) ReadFileHandler(args *ReadFileArgs, reply *[]byte) (err error) {
defer func() {
if r := recover(); r != nil {
// Recover any panic and return ErrCacheFull.
err = bytes.ErrTooLarge
}
}() // Do not crash the server.
if !isRPCTokenValid(args.Token) { if !isRPCTokenValid(args.Token) {
return errors.New("Invalid token") return errors.New("Invalid token")
} }
n, err := s.storage.ReadFile(args.Vol, args.Path, args.Offset, args.Buffer) // Allocate the requested buffer from the client.
if err != nil { *reply = make([]byte, args.Size)
return err var n int64
n, err = s.storage.ReadFile(args.Vol, args.Path, args.Offset, *reply)
// Sending an error over the rpc layer, would cause unmarshalling to fail. In situations
// when we have short read i.e `io.ErrUnexpectedEOF` treat it as good condition and copy
// the buffer properly.
if err == io.ErrUnexpectedEOF {
// Reset to nil as good condition.
err = nil
} }
*reply = n *reply = (*reply)[0:n]
return nil return err
} }
// AppendFileHandler - append file handler is rpc wrapper to append file. // AppendFileHandler - append file handler is rpc wrapper to append file.