github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/go-ethereum-master/cmd/swarm/swarm-smoke/upload_and_sync.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "bytes" 21 "crypto/md5" 22 "crypto/rand" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "net/http" 27 "os" 28 "os/exec" 29 "strings" 30 "sync" 31 "time" 32 33 "github.com/ethereum/go-ethereum/log" 34 "github.com/pborman/uuid" 35 36 cli "gopkg.in/urfave/cli.v1" 37 ) 38 39 func generateEndpoints(scheme string, cluster string, from int, to int) { 40 if cluster == "prod" { 41 cluster = "" 42 } else { 43 cluster = cluster + "." 44 } 45 46 for port := from; port <= to; port++ { 47 endpoints = append(endpoints, fmt.Sprintf("%s://%v.%sswarm-gateways.net", scheme, port, cluster)) 48 } 49 50 if includeLocalhost { 51 endpoints = append(endpoints, "http://localhost:8500") 52 } 53 } 54 55 func cliUploadAndSync(c *cli.Context) error { 56 defer func(now time.Time) { log.Info("total time", "time", time.Since(now), "size", filesize) }(time.Now()) 57 58 generateEndpoints(scheme, cluster, from, to) 59 60 log.Info("uploading to " + endpoints[0] + " and syncing") 61 62 f, cleanup := generateRandomFile(filesize * 1000000) 63 defer cleanup() 64 65 hash, err := upload(f, endpoints[0]) 66 if err != nil { 67 log.Error(err.Error()) 68 return err 69 } 70 71 fhash, err := digest(f) 72 if err != nil { 73 log.Error(err.Error()) 74 return err 75 } 76 77 log.Info("uploaded successfully", "hash", hash, "digest", fmt.Sprintf("%x", fhash)) 78 79 if filesize < 10 { 80 time.Sleep(15 * time.Second) 81 } else { 82 time.Sleep(2 * time.Duration(filesize) * time.Second) 83 } 84 85 wg := sync.WaitGroup{} 86 for _, endpoint := range endpoints { 87 endpoint := endpoint 88 ruid := uuid.New()[:8] 89 wg.Add(1) 90 go func(endpoint string, ruid string) { 91 for { 92 err := fetch(hash, endpoint, fhash, ruid) 93 if err != nil { 94 continue 95 } 96 97 wg.Done() 98 return 99 } 100 }(endpoint, ruid) 101 } 102 wg.Wait() 103 log.Info("all endpoints synced random file successfully") 104 105 return nil 106 } 107 108 // fetch is getting the requested `hash` from the `endpoint` and compares it with the `original` file 109 func fetch(hash string, endpoint string, original []byte, ruid string) error { 110 log.Trace("sleeping", "ruid", ruid) 111 time.Sleep(1 * time.Second) 112 113 log.Trace("http get request", "ruid", ruid, "api", endpoint, "hash", hash) 114 res, err := http.Get(endpoint + "/bzz:/" + hash + "/") 115 if err != nil { 116 log.Warn(err.Error(), "ruid", ruid) 117 return err 118 } 119 log.Trace("http get response", "ruid", ruid, "api", endpoint, "hash", hash, "code", res.StatusCode, "len", res.ContentLength) 120 121 if res.StatusCode != 200 { 122 err := fmt.Errorf("expected status code %d, got %v", 200, res.StatusCode) 123 log.Warn(err.Error(), "ruid", ruid) 124 return err 125 } 126 127 defer res.Body.Close() 128 129 rdigest, err := digest(res.Body) 130 if err != nil { 131 log.Warn(err.Error(), "ruid", ruid) 132 return err 133 } 134 135 if !bytes.Equal(rdigest, original) { 136 err := fmt.Errorf("downloaded imported file md5=%x is not the same as the generated one=%x", rdigest, original) 137 log.Warn(err.Error(), "ruid", ruid) 138 return err 139 } 140 141 log.Trace("downloaded file matches random file", "ruid", ruid, "len", res.ContentLength) 142 143 return nil 144 } 145 146 // upload is uploading a file `f` to `endpoint` via the `swarm up` cmd 147 func upload(f *os.File, endpoint string) (string, error) { 148 var out bytes.Buffer 149 cmd := exec.Command("swarm", "--bzzapi", endpoint, "up", f.Name()) 150 cmd.Stdout = &out 151 err := cmd.Run() 152 if err != nil { 153 return "", err 154 } 155 hash := strings.TrimRight(out.String(), "\r\n") 156 return hash, nil 157 } 158 159 func digest(r io.Reader) ([]byte, error) { 160 h := md5.New() 161 _, err := io.Copy(h, r) 162 if err != nil { 163 return nil, err 164 } 165 return h.Sum(nil), nil 166 } 167 168 // generateRandomFile is creating a temporary file with the requested byte size 169 func generateRandomFile(size int) (f *os.File, teardown func()) { 170 // create a tmp file 171 tmp, err := ioutil.TempFile("", "swarm-test") 172 if err != nil { 173 panic(err) 174 } 175 176 // callback for tmp file cleanup 177 teardown = func() { 178 tmp.Close() 179 os.Remove(tmp.Name()) 180 } 181 182 buf := make([]byte, size) 183 _, err = rand.Read(buf) 184 if err != nil { 185 panic(err) 186 } 187 ioutil.WriteFile(tmp.Name(), buf, 0755) 188 189 return tmp, teardown 190 }