github.com/annchain/OG@v0.0.9/tests/txsync/tx_sync.go (about) 1 // Copyright © 2019 Annchain Authors <EMAIL ADDRESS> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package main 15 16 import ( 17 "encoding/json" 18 "fmt" 19 "github.com/annchain/OG/wserver" 20 "github.com/gorilla/websocket" 21 "github.com/sirupsen/logrus" 22 "net/http" 23 "net/url" 24 "time" 25 ) 26 27 type pm struct { 28 message string 29 port int 30 } 31 32 const PORT_OFFSET_WS = 2 33 const PORT_OFFSET_RPC = 0 34 const PORT_START = 8000 35 const PORT_GAP = 100 36 const NODES = 30 37 const REPORT_INTERVAL_SECONDS = 5 38 39 func main() { 40 logrus.SetFormatter(&logrus.TextFormatter{ 41 ForceColors: true, 42 FullTimestamp: true, 43 }) 44 logrus.SetLevel(logrus.InfoLevel) 45 agg := make(chan pm, 1000) 46 count := 0 47 48 maxPort := PORT_START 49 50 for port := PORT_START; port <= PORT_START+NODES*PORT_GAP; port += PORT_GAP { 51 err := startListen(agg, port) 52 if err != nil { 53 continue 54 } 55 if port > maxPort { 56 maxPort = port 57 } 58 count += 1 59 } 60 mapcount := make(map[string]map[int]struct{}) 61 62 deleted := 0 63 64 ticker := time.NewTicker(time.Second * REPORT_INTERVAL_SECONDS) 65 defer ticker.Stop() 66 67 http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 5 68 69 lastCheck := time.Now() 70 71 for { 72 select { 73 case <-ticker.C: 74 logrus.Warn("Ticker") 75 toDelete := []string{} 76 for k := range mapcount { 77 changed := false 78 // manual query to double confirm 79 for missingPort := PORT_START; missingPort <= maxPort; missingPort += PORT_GAP { 80 if _, ok := mapcount[k][missingPort]; !ok { 81 if manualQuery(missingPort, k) { 82 mapcount[k][missingPort] = struct{}{} 83 changed = true 84 logrus.WithField("hash", k).WithField("port", missingPort). 85 Debug("manually fetched by rpc. ws missing?") 86 } 87 } 88 } 89 if !changed { 90 if len(mapcount[k]) == count { 91 logrus.WithField("hash", k).Debug("Should be fulfilled but not.") 92 toDelete = append(toDelete, k) 93 } else { 94 logrus.WithField("key", k).WithField("value", mapcount[k]).Warn("Still not fulfilled") 95 } 96 } 97 } 98 for _, k := range toDelete { 99 delete(mapcount, k) 100 deleted += 1 101 } 102 logrus.WithField("count", deleted). 103 WithField("v", float64(deleted)/(time.Since(lastCheck).Seconds())). 104 Info("tps") 105 lastCheck = time.Now() 106 deleted = 0 107 case m := <-agg: 108 uidata := &wserver.UIData{} 109 err := json.Unmarshal([]byte(m.message), uidata) 110 if err != nil { 111 logrus.WithField("port", m.port).WithError(err).Error("unmarshal") 112 return 113 } 114 for _, node := range uidata.Nodes { 115 key := node.Data.Unit 116 //logrus.WithFields(logrus.Fields{ 117 // "port": m.port, 118 // "len": len(uidata.Nodes), 119 // "tx": key, 120 //}).Debug("new tx") 121 122 if _, ok := mapcount[key]; !ok { 123 mapcount[key] = make(map[int]struct{}) 124 } 125 mapcount[key][m.port] = struct{}{} 126 if len(mapcount[key]) == count { 127 logrus.WithField("key", key).Debug("fully announced") 128 delete(mapcount, key) 129 deleted += 1 130 } 131 } 132 } 133 } 134 } 135 func manualQuery(port int, hash string) bool { 136 resp, err := http.Get(fmt.Sprintf("http://localhost:%d/transaction?hash=%s", port+PORT_OFFSET_RPC, hash)) 137 138 if err != nil { 139 logrus.WithField("port", port).WithError(err).Warn("Request query error") 140 return false 141 } 142 defer resp.Body.Close() 143 return true 144 145 } 146 func startListen(agg chan pm, port int) error { 147 wsPort := port + PORT_OFFSET_WS 148 u := url.URL{Scheme: "ws", Host: fmt.Sprintf("127.0.0.1:%d", wsPort), Path: "/ws"} 149 logrus.Infof("connecting to %s", u.String()) 150 151 c, _, err := websocket.DefaultDialer.Dial(u.String(), nil) 152 if err != nil { 153 logrus.WithError(err).Errorf("dial") 154 return err 155 } 156 157 go func() { 158 err := c.WriteMessage(websocket.TextMessage, []byte("{\"event\": \"new_unit\"}")) 159 if err != nil { 160 logrus.WithField("port", wsPort).Error("write") 161 return 162 } 163 164 for { 165 _, message, err := c.ReadMessage() 166 if err != nil { 167 logrus.WithError(err).WithField("port", wsPort).Error("read error") 168 return 169 } 170 agg <- pm{message: string(message), port: port} 171 } 172 }() 173 return nil 174 }