github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/imagetool/testDownloadSpeed.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"time"
     9  
    10  	imgclient "github.com/Cloud-Foundations/Dominator/imageserver/client"
    11  	"github.com/Cloud-Foundations/Dominator/lib/filesystem"
    12  	"github.com/Cloud-Foundations/Dominator/lib/format"
    13  	"github.com/Cloud-Foundations/Dominator/lib/hash"
    14  	"github.com/Cloud-Foundations/Dominator/lib/log"
    15  	"github.com/Cloud-Foundations/Dominator/lib/objectserver"
    16  )
    17  
    18  func testDownloadSpeedSubcommand(args []string, logger log.DebugLogger) error {
    19  	if err := testDownloadSpeed(args[0], logger); err != nil {
    20  		return fmt.Errorf("Error testing download speed: %s", err)
    21  	}
    22  	return nil
    23  }
    24  
    25  func testDownloadSpeed(imageName string, logger log.Logger) error {
    26  	imageSClient, objClient := getClients()
    27  	isDir, err := imgclient.CheckDirectory(imageSClient, imageName)
    28  	if err != nil {
    29  		return err
    30  	}
    31  	if isDir {
    32  		name, err := imgclient.FindLatestImage(imageSClient, imageName, false)
    33  		if err != nil {
    34  			return err
    35  		} else {
    36  			imageName = name
    37  		}
    38  	}
    39  	startTime := time.Now()
    40  	img, err := imgclient.GetImageWithTimeout(imageSClient, imageName, *timeout)
    41  	if err != nil {
    42  		return err
    43  	}
    44  	if img == nil {
    45  		return errors.New(imageName + ": not found")
    46  	}
    47  	finishedTime := time.Now()
    48  	logger.Printf("downloaded image metadata in %s\n",
    49  		format.Duration(finishedTime.Sub(startTime)))
    50  	hashes := make([]hash.Hash, 0, len(img.FileSystem.InodeTable))
    51  	for _, inode := range img.FileSystem.InodeTable {
    52  		if inode, ok := inode.(*filesystem.RegularInode); ok {
    53  			if inode.Size > 0 {
    54  				hashes = append(hashes, inode.Hash)
    55  			}
    56  		}
    57  	}
    58  	startTime = time.Now()
    59  	objectsReader, err := objClient.GetObjects(hashes)
    60  	if err != nil {
    61  		return err
    62  	}
    63  	defer objectsReader.Close()
    64  	var totalBytes uint64
    65  	buffer := make([]byte, 32<<10)
    66  	for range hashes {
    67  		if length, err := readOneObject(objectsReader, buffer); err != nil {
    68  			return err
    69  		} else {
    70  			totalBytes += length
    71  		}
    72  	}
    73  	finishedTime = time.Now()
    74  	downloadTime := finishedTime.Sub(startTime)
    75  	downloadSpeed := float64(totalBytes) / downloadTime.Seconds()
    76  	logger.Printf("downloaded %s (%d objects) in %s (%s/s)\n",
    77  		format.FormatBytes(totalBytes), len(hashes),
    78  		format.Duration(downloadTime),
    79  		format.FormatBytes(uint64(downloadSpeed)))
    80  	return nil
    81  }
    82  
    83  func readOneObject(objectsReader objectserver.ObjectsReader,
    84  	buffer []byte) (uint64, error) {
    85  	_, reader, err := objectsReader.NextObject()
    86  	if err != nil {
    87  		return 0, err
    88  	}
    89  	defer reader.Close()
    90  	nCopied, err := io.CopyBuffer(ioutil.Discard, reader, buffer)
    91  	return uint64(nCopied), err
    92  }