github.com/codingfuture/orig-energi3@v0.8.4/cmd/swarm/swarm-smoke/upload_and_sync.go (about) 1 // Copyright 2018 The Energi Core Authors 2 // Copyright 2018 The go-ethereum Authors 3 // This file is part of Energi Core. 4 // 5 // Energi Core is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Energi Core is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Energi Core. If not, see <http://www.gnu.org/licenses/>. 17 18 package main 19 20 import ( 21 "bytes" 22 "context" 23 "fmt" 24 "io/ioutil" 25 "math/rand" 26 "os" 27 "sync" 28 "time" 29 30 "github.com/ethereum/go-ethereum/log" 31 "github.com/ethereum/go-ethereum/metrics" 32 "github.com/ethereum/go-ethereum/rpc" 33 "github.com/ethereum/go-ethereum/swarm/api" 34 "github.com/ethereum/go-ethereum/swarm/storage" 35 "github.com/ethereum/go-ethereum/swarm/testutil" 36 "github.com/pborman/uuid" 37 38 cli "gopkg.in/urfave/cli.v1" 39 ) 40 41 func uploadAndSyncCmd(ctx *cli.Context, tuid string) error { 42 randomBytes := testutil.RandomBytes(seed, filesize*1000) 43 44 errc := make(chan error) 45 46 go func() { 47 errc <- uplaodAndSync(ctx, randomBytes, tuid) 48 }() 49 50 select { 51 case err := <-errc: 52 if err != nil { 53 metrics.GetOrRegisterCounter(fmt.Sprintf("%s.fail", commandName), nil).Inc(1) 54 } 55 return err 56 case <-time.After(time.Duration(timeout) * time.Second): 57 metrics.GetOrRegisterCounter(fmt.Sprintf("%s.timeout", commandName), nil).Inc(1) 58 59 e := fmt.Errorf("timeout after %v sec", timeout) 60 // trigger debug functionality on randomBytes 61 err := trackChunks(randomBytes[:]) 62 if err != nil { 63 e = fmt.Errorf("%v; triggerChunkDebug failed: %v", e, err) 64 } 65 66 return e 67 } 68 } 69 70 func trackChunks(testData []byte) error { 71 log.Warn("Test timed out; running chunk debug sequence") 72 73 addrs, err := getAllRefs(testData) 74 if err != nil { 75 return err 76 } 77 log.Trace("All references retrieved") 78 79 // has-chunks 80 for _, host := range hosts { 81 httpHost := fmt.Sprintf("ws://%s:%d", host, 39795) 82 log.Trace("Calling `Has` on host", "httpHost", httpHost) 83 rpcClient, err := rpc.Dial(httpHost) 84 if err != nil { 85 log.Trace("Error dialing host", "err", err) 86 return err 87 } 88 log.Trace("rpc dial ok") 89 var hasInfo []api.HasInfo 90 err = rpcClient.Call(&hasInfo, "bzz_has", addrs) 91 if err != nil { 92 log.Trace("Error calling host", "err", err) 93 return err 94 } 95 log.Trace("rpc call ok") 96 count := 0 97 for _, info := range hasInfo { 98 if !info.Has { 99 count++ 100 log.Error("Host does not have chunk", "host", httpHost, "chunk", info.Addr) 101 } 102 } 103 if count == 0 { 104 log.Info("Host reported to have all chunks", "host", httpHost) 105 } 106 } 107 return nil 108 } 109 110 func getAllRefs(testData []byte) (storage.AddressCollection, error) { 111 log.Trace("Getting all references for given root hash") 112 datadir, err := ioutil.TempDir("", "chunk-debug") 113 if err != nil { 114 return nil, fmt.Errorf("unable to create temp dir: %v", err) 115 } 116 defer os.RemoveAll(datadir) 117 fileStore, err := storage.NewLocalFileStore(datadir, make([]byte, 32)) 118 if err != nil { 119 return nil, err 120 } 121 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(trackTimeout)*time.Second) 122 defer cancel() 123 124 reader := bytes.NewReader(testData) 125 return fileStore.GetAllReferences(ctx, reader, false) 126 } 127 128 func uplaodAndSync(c *cli.Context, randomBytes []byte, tuid string) error { 129 log.Info("uploading to "+httpEndpoint(hosts[0])+" and syncing", "tuid", tuid, "seed", seed) 130 131 t1 := time.Now() 132 hash, err := upload(randomBytes, httpEndpoint(hosts[0])) 133 if err != nil { 134 log.Error(err.Error()) 135 return err 136 } 137 t2 := time.Since(t1) 138 metrics.GetOrRegisterResettingTimer("upload-and-sync.upload-time", nil).Update(t2) 139 140 fhash, err := digest(bytes.NewReader(randomBytes)) 141 if err != nil { 142 log.Error(err.Error()) 143 return err 144 } 145 146 log.Info("uploaded successfully", "tuid", tuid, "hash", hash, "took", t2, "digest", fmt.Sprintf("%x", fhash)) 147 148 time.Sleep(time.Duration(syncDelay) * time.Second) 149 150 wg := sync.WaitGroup{} 151 if single { 152 randIndex := 1 + rand.Intn(len(hosts)-1) 153 ruid := uuid.New()[:8] 154 wg.Add(1) 155 go func(endpoint string, ruid string) { 156 for { 157 start := time.Now() 158 err := fetch(hash, endpoint, fhash, ruid, tuid) 159 if err != nil { 160 continue 161 } 162 ended := time.Since(start) 163 164 metrics.GetOrRegisterResettingTimer("upload-and-sync.single.fetch-time", nil).Update(ended) 165 log.Info("fetch successful", "tuid", tuid, "ruid", ruid, "took", ended, "endpoint", endpoint) 166 wg.Done() 167 return 168 } 169 }(httpEndpoint(hosts[randIndex]), ruid) 170 } else { 171 for _, endpoint := range hosts[1:] { 172 ruid := uuid.New()[:8] 173 wg.Add(1) 174 go func(endpoint string, ruid string) { 175 for { 176 start := time.Now() 177 err := fetch(hash, endpoint, fhash, ruid, tuid) 178 if err != nil { 179 continue 180 } 181 ended := time.Since(start) 182 183 metrics.GetOrRegisterResettingTimer("upload-and-sync.each.fetch-time", nil).Update(ended) 184 log.Info("fetch successful", "tuid", tuid, "ruid", ruid, "took", ended, "endpoint", endpoint) 185 wg.Done() 186 return 187 } 188 }(httpEndpoint(endpoint), ruid) 189 } 190 } 191 wg.Wait() 192 log.Info("all hosts synced random file successfully") 193 194 return nil 195 }