Пример #1
0
func (rpc *grpcService) readFrom(request *pb.ReadRequest, reader io.ReaderAt, stream pb.ByteStream_ReadServer) error {
	limit := int(request.ReadLimit)
	if limit < 0 {
		return grpc.Errorf(codes.InvalidArgument, "Read(): read_limit=%d is invalid", limit)
	}
	offset := request.ReadOffset
	if offset < 0 {
		return grpc.Errorf(codes.InvalidArgument, "Read(): offset=%d is invalid", offset)
	}

	var buf []byte
	if limit > 0 {
		buf = make([]byte, limit)
	} else {
		buf = make([]byte, 1024*1024) // 1M buffer is reasonable.
	}
	bytesSent := 0
	for limit == 0 || bytesSent < limit {
		n, err := reader.ReadAt(buf, offset)
		if n > 0 {
			if err := stream.Send(&pb.ReadResponse{Data: buf[:n]}); err != nil {
				return grpc.Errorf(grpc.Code(err), "Send(resourceName=%q offset=%d): %v", request.ResourceName, offset, grpc.ErrorDesc(err))
			}
		} else if err == nil {
			return grpc.Errorf(codes.Internal, "nil error on empty read: io.ReaderAt contract violated")
		}
		offset += int64(n)
		bytesSent += n
		if err == io.EOF {
			break
		}
		if err != nil {
			return grpc.Errorf(codes.Unknown, "ReadAt(resourceName=%q offset=%d): %v", request.ResourceName, offset, err)
		}
	}
	return nil
}
Пример #2
0
// Read handles a pb.ReadRequest sending bytes to the pb.ByteStream_ReadServer
// Implements bytestream.proto "rpc Read(ReadRequest) returns (stream ReadResponse)"
func (rpc *grpcService) Read(request *pb.ReadRequest, stream pb.ByteStream_ReadServer) error {
	if rpc.parent.readHandler == nil {
		return grpc.Errorf(codes.Unimplemented, "instance of NewServer(readHandler = nil) rejects all reads")
	}
	if request == nil {
		return grpc.Errorf(codes.Internal, "Read(ReadRequest == nil)")
	}
	if request.ResourceName == "" {
		return grpc.Errorf(codes.InvalidArgument, "ReadRequest: empty or missing resource_name")
	}

	reader, err := rpc.parent.readHandler.GetReader(stream.Context(), request.ResourceName)
	if err != nil {
		return err
	}
	if err = rpc.readFrom(request, reader, stream); err != nil {
		rpc.parent.readHandler.Close(stream.Context(), request.ResourceName)
		return err
	}
	if err = rpc.parent.readHandler.Close(stream.Context(), request.ResourceName); err != nil {
		return err
	}
	return nil
}