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 }