github.com/Cloud-Foundations/Dominator@v0.3.4/imageunpacker/unpacker/getRaw.go (about)

     1  package unpacker
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"time"
     9  
    10  	"github.com/Cloud-Foundations/Dominator/lib/format"
    11  	proto "github.com/Cloud-Foundations/Dominator/proto/imageunpacker"
    12  )
    13  
    14  func (u *Unpacker) getRaw(streamName string) (io.ReadCloser, uint64, error) {
    15  	u.updateUsageTime()
    16  	defer u.updateUsageTime()
    17  	streamInfo := u.getStream(streamName)
    18  	if streamInfo == nil {
    19  		return nil, 0, errors.New("unknown stream")
    20  	}
    21  	errorChannel := make(chan error, 1)
    22  	readerChannel := make(chan *sizedReader, 1)
    23  	request := requestType{
    24  		request:       requestGetRaw,
    25  		errorChannel:  errorChannel,
    26  		readerChannel: readerChannel,
    27  	}
    28  	streamInfo.requestChannel <- request
    29  	select {
    30  	case reader := <-readerChannel:
    31  		return reader, reader.size, nil
    32  	case err := <-errorChannel:
    33  		if err != nil {
    34  			return nil, 0, err
    35  		}
    36  		return nil, 0, errors.New("no reader")
    37  	}
    38  }
    39  
    40  func (stream *streamManagerState) getRaw(
    41  	readerChannel chan<- *sizedReader) error {
    42  	if err := stream.prepareForCopy(); err != nil {
    43  		return err
    44  	}
    45  	streamInfo := stream.streamInfo
    46  	stream.unpacker.rwMutex.RLock()
    47  	device := stream.unpacker.pState.Devices[streamInfo.DeviceId]
    48  	stream.unpacker.rwMutex.RUnlock()
    49  	deviceNode := filepath.Join("/dev", device.DeviceName)
    50  	file, err := os.Open(deviceNode)
    51  	if err != nil {
    52  		return err
    53  	}
    54  	defer file.Close()
    55  	closeNotifier := make(chan struct{}, 1)
    56  	streamInfo.status = proto.StatusStreamTransferring
    57  	reader := &sizedReader{
    58  		closeNotifier: closeNotifier,
    59  		reader:        file,
    60  		size:          device.size,
    61  	}
    62  	readerChannel <- reader
    63  	startTime := time.Now()
    64  	<-closeNotifier
    65  	timeTaken := time.Since(startTime)
    66  	streamInfo.dualLogger.Printf("Transferred(%s) %s in %s (%s/s)\n",
    67  		stream.streamName, format.FormatBytes(reader.nRead),
    68  		format.Duration(timeTaken),
    69  		format.FormatBytes(uint64(float64(reader.nRead)/timeTaken.Seconds())))
    70  	streamInfo.status = proto.StatusStreamNotMounted
    71  	return nil
    72  }
    73  
    74  func (rc *sizedReader) Close() error {
    75  	if rc.closeNotifier != nil {
    76  		rc.closeNotifier <- struct{}{}
    77  	}
    78  	return rc.err
    79  }
    80  
    81  func (rc *sizedReader) Read(p []byte) (int, error) {
    82  	if rc.err != nil {
    83  		return 0, rc.err
    84  	}
    85  	nRead, err := rc.reader.Read(p)
    86  	rc.nRead += uint64(nRead)
    87  	rc.err = err
    88  	if err != nil {
    89  		rc.closeNotifier <- struct{}{}
    90  		rc.closeNotifier = nil
    91  	}
    92  	return nRead, err
    93  }