github.com/XinFinOrg/xdcchain@v1.1.0/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 "context" 22 "fmt" 23 "io/ioutil" 24 "math/rand" 25 "os" 26 "sync" 27 "time" 28 29 "github.com/ethereum/go-ethereum/log" 30 "github.com/ethereum/go-ethereum/metrics" 31 "github.com/ethereum/go-ethereum/rpc" 32 "github.com/ethereum/go-ethereum/swarm/api" 33 "github.com/ethereum/go-ethereum/swarm/storage" 34 "github.com/ethereum/go-ethereum/swarm/testutil" 35 "github.com/pborman/uuid" 36 37 cli "gopkg.in/urfave/cli.v1" 38 ) 39 40 func uploadAndSyncCmd(ctx *cli.Context, tuid string) error { 41 randomBytes := testutil.RandomBytes(seed, filesize*1000) 42 43 errc := make(chan error) 44 45 go func() { 46 errc <- uplaodAndSync(ctx, randomBytes, tuid) 47 }() 48 49 select { 50 case err := <-errc: 51 if err != nil { 52 metrics.GetOrRegisterCounter(fmt.Sprintf("%s.fail", commandName), nil).Inc(1) 53 } 54 return err 55 case <-time.After(time.Duration(timeout) * time.Second): 56 metrics.GetOrRegisterCounter(fmt.Sprintf("%s.timeout", commandName), nil).Inc(1) 57 58 e := fmt.Errorf("timeout after %v sec", timeout) 59 // trigger debug functionality on randomBytes 60 err := trackChunks(randomBytes[:]) 61 if err != nil { 62 e = fmt.Errorf("%v; triggerChunkDebug failed: %v", e, err) 63 } 64 65 return e 66 } 67 } 68 69 func trackChunks(testData []byte) error { 70 log.Warn("Test timed out; running chunk debug sequence") 71 72 addrs, err := getAllRefs(testData) 73 if err != nil { 74 return err 75 } 76 log.Trace("All references retrieved") 77 78 // has-chunks 79 for _, host := range hosts { 80 httpHost := fmt.Sprintf("ws://%s:%d", host, 8546) 81 log.Trace("Calling `Has` on host", "httpHost", httpHost) 82 rpcClient, err := rpc.Dial(httpHost) 83 if err != nil { 84 log.Trace("Error dialing host", "err", err) 85 return err 86 } 87 log.Trace("rpc dial ok") 88 var hasInfo []api.HasInfo 89 err = rpcClient.Call(&hasInfo, "bzz_has", addrs) 90 if err != nil { 91 log.Trace("Error calling host", "err", err) 92 return err 93 } 94 log.Trace("rpc call ok") 95 count := 0 96 for _, info := range hasInfo { 97 if !info.Has { 98 count++ 99 log.Error("Host does not have chunk", "host", httpHost, "chunk", info.Addr) 100 } 101 } 102 if count == 0 { 103 log.Info("Host reported to have all chunks", "host", httpHost) 104 } 105 } 106 return nil 107 } 108 109 func getAllRefs(testData []byte) (storage.AddressCollection, error) { 110 log.Trace("Getting all references for given root hash") 111 datadir, err := ioutil.TempDir("", "chunk-debug") 112 if err != nil { 113 return nil, fmt.Errorf("unable to create temp dir: %v", err) 114 } 115 defer os.RemoveAll(datadir) 116 fileStore, err := storage.NewLocalFileStore(datadir, make([]byte, 32)) 117 if err != nil { 118 return nil, err 119 } 120 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(trackTimeout)*time.Second) 121 defer cancel() 122 123 reader := bytes.NewReader(testData) 124 return fileStore.GetAllReferences(ctx, reader, false) 125 } 126 127 func uplaodAndSync(c *cli.Context, randomBytes []byte, tuid string) error { 128 log.Info("uploading to "+httpEndpoint(hosts[0])+" and syncing", "tuid", tuid, "seed", seed) 129 130 t1 := time.Now() 131 hash, err := upload(randomBytes, httpEndpoint(hosts[0])) 132 if err != nil { 133 log.Error(err.Error()) 134 return err 135 } 136 t2 := time.Since(t1) 137 metrics.GetOrRegisterResettingTimer("upload-and-sync.upload-time", nil).Update(t2) 138 139 fhash, err := digest(bytes.NewReader(randomBytes)) 140 if err != nil { 141 log.Error(err.Error()) 142 return err 143 } 144 145 log.Info("uploaded successfully", "tuid", tuid, "hash", hash, "took", t2, "digest", fmt.Sprintf("%x", fhash)) 146 147 time.Sleep(time.Duration(syncDelay) * time.Second) 148 149 wg := sync.WaitGroup{} 150 if single { 151 randIndex := 1 + rand.Intn(len(hosts)-1) 152 ruid := uuid.New()[:8] 153 wg.Add(1) 154 go func(endpoint string, ruid string) { 155 for { 156 start := time.Now() 157 err := fetch(hash, endpoint, fhash, ruid, tuid) 158 if err != nil { 159 continue 160 } 161 ended := time.Since(start) 162 163 metrics.GetOrRegisterResettingTimer("upload-and-sync.single.fetch-time", nil).Update(ended) 164 log.Info("fetch successful", "tuid", tuid, "ruid", ruid, "took", ended, "endpoint", endpoint) 165 wg.Done() 166 return 167 } 168 }(httpEndpoint(hosts[randIndex]), ruid) 169 } else { 170 for _, endpoint := range hosts[1:] { 171 ruid := uuid.New()[:8] 172 wg.Add(1) 173 go func(endpoint string, ruid string) { 174 for { 175 start := time.Now() 176 err := fetch(hash, endpoint, fhash, ruid, tuid) 177 if err != nil { 178 continue 179 } 180 ended := time.Since(start) 181 182 metrics.GetOrRegisterResettingTimer("upload-and-sync.each.fetch-time", nil).Update(ended) 183 log.Info("fetch successful", "tuid", tuid, "ruid", ruid, "took", ended, "endpoint", endpoint) 184 wg.Done() 185 return 186 } 187 }(httpEndpoint(endpoint), ruid) 188 } 189 } 190 wg.Wait() 191 log.Info("all hosts synced random file successfully") 192 193 return nil 194 }