├── .dockerignore ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── agent ├── agent.go └── agent_msg.go ├── arraymap ├── arraymap.go └── arraymap_test.go ├── codec ├── codec.go └── codec_test.go ├── config └── config.go ├── log └── logger.go ├── main.go ├── message ├── Makefile ├── message.pb.go ├── message.proto └── messagepb_test.go ├── node └── node.go ├── rest └── server.go └── test ├── genlist.py ├── process_log.py ├── query_handler.sh ├── run_cluster.py ├── run_serfcluster.py ├── rungog.sh └── timer.go /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | *.txt 26 | 27 | # executable 28 | gog 29 | test/log/ 30 | test/test 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang 2 | ENV GOPATH /root/gopher 3 | ENV GOGPATH github.com/go-distributed/gog 4 | RUN go get $GOGPATH 5 | RUN go install $GOGPATH 6 | ENTRYPOINT $GOPATH/bin/gog -user-message-handler=$GOPATH/src/$GOGPATH/test/query_handler.sh 7 | EXPOSE 8424 9424 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | gog 2 | === 3 | 4 | Gossip Over Gophers 5 | 6 | [![GoDoc] (https://godoc.org/github.com/go-distributed/gog?status.png)](https://godoc.org/github.com/go-distributed/gog) 7 | 8 | [Writeup] (https://drive.google.com/file/d/0BzkE2qUvDHtpTFdZRVFCWDI0dWM/view?usp=sharing) 9 | 10 | ###How to build: 11 | 12 | ```shell 13 | $ go build 14 | ``` 15 | 16 | Show usage: 17 | 18 | ```shell 19 | $ ./gog -h 20 | ``` 21 | 22 | 23 | Run a standalone node: 24 | 25 | ```shell 26 | $ ./gog 27 | ``` 28 | 29 | To join an existing cluster: 30 | 31 | 1. Form a two-node-cluster 32 | 33 | ```shell 34 | $ ./gog -addr="localhost:8000" -rest-addr="localhost:8001" 35 | $ ./gog -addr="localhost:8002" -rest-addr="localhost:8003" 36 | ``` 37 | 38 | 2. Let the first node join the second node 39 | 40 | ```shell 41 | $ curl http://localhost:8001/api/join -d peer=localhost:8002 42 | ``` 43 | 44 | 3. Show the view in the first node 45 | 46 | ```shell 47 | $ curl http://localhost:8001/api/list 48 | {"active_view":[{"id":"localhost:8002","address":"localhost:8002"}],"passive_view":[]} 49 | ``` 50 | 51 | You can also provide a json file contains a list of nodes: 52 | ```shell 53 | $ cat peers.json 54 | ["localhost:8000", "localhost:8001", "localhost:8002", "localhost:8003"] 55 | 56 | $ curl -d @peers.json -H "Content-Type: application/json" http://localhost:8001/api/join 57 | ``` 58 | 59 | To broadcast a message: 60 | 61 | ```shell 62 | $ curl http://localhost:8001/api/broadcast -d message=hello 63 | ``` 64 | -------------------------------------------------------------------------------- /agent/agent.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "crypto/sha1" 5 | "encoding/json" 6 | "math/rand" 7 | "net" 8 | "os" 9 | "time" 10 | 11 | "github.com/go-distributed/gog/arraymap" 12 | "github.com/go-distributed/gog/codec" 13 | "github.com/go-distributed/gog/config" 14 | "github.com/go-distributed/gog/message" 15 | "github.com/go-distributed/gog/node" 16 | 17 | "code.google.com/p/gogoprotobuf/proto" 18 | log "github.com/go-distributed/gog/log" 19 | ) 20 | 21 | // MessageHandler is the message handler. 22 | type MessageHandler func([]byte) 23 | 24 | // Agent describes the interface of an agent. 25 | type Agent interface { 26 | // Serve starts a standalone agent, waiting for 27 | // incoming connections. 28 | Serve() error 29 | // Join joins the peers. 30 | Join(peerAddrs ...string) error 31 | // Leave causes the agent to leave the cluster. 32 | Leave() 33 | // Broadcast broadcasts a message to the cluster. 34 | Broadcast(msg []byte) error 35 | // RegisterMessageHandler registers a user provided callback. 36 | RegisterMessageHandler(mh MessageHandler) 37 | // List prints the infomation in two views. 38 | List() ([]byte, error) 39 | } 40 | 41 | // agent implements the Agent interface. 42 | type agent struct { 43 | // The id of the agent. 44 | id uint64 45 | // Configuration. 46 | cfg *config.Config 47 | // Active View. 48 | aView *arraymap.ArrayMap 49 | // Passive View. 50 | pView *arraymap.ArrayMap 51 | // TCP listener. 52 | ln *net.TCPListener 53 | // The codec. 54 | codec codec.Codec 55 | // Message buffer. 56 | msgBuffer *arraymap.ArrayMap 57 | // FaildMessage buffer. 58 | failmsgBuffer *arraymap.ArrayMap 59 | // The user message callback. 60 | msgHandler MessageHandler 61 | } 62 | 63 | // view is a struct that encapsulates the active and passive 64 | // view. It is for creating json files. 65 | type view struct { 66 | // Active View. 67 | AView *arraymap.ArrayMap `json:"active_view"` 68 | // Passive View. 69 | PView *arraymap.ArrayMap `json:"passive_view"` 70 | } 71 | 72 | func init() { 73 | rand.Seed(time.Now().UnixNano()) 74 | } 75 | 76 | func GenID() (n uint64) { 77 | for n == 0 { 78 | n = uint64(rand.Int63()) 79 | } 80 | return 81 | } 82 | 83 | // NewAgent creates a new agent. 84 | func NewAgent(cfg *config.Config) Agent { 85 | // Create a codec and register messages. 86 | codec := codec.NewProtobufCodec() 87 | codec.Register(&message.UserMessage{}) 88 | codec.Register(&message.Join{}) 89 | codec.Register(&message.JoinReply{}) 90 | codec.Register(&message.ForwardJoin{}) 91 | codec.Register(&message.Neighbor{}) 92 | codec.Register(&message.NeighborReply{}) 93 | codec.Register(&message.Disconnect{}) 94 | codec.Register(&message.Shuffle{}) 95 | codec.Register(&message.ShuffleReply{}) 96 | 97 | return &agent{ 98 | id: GenID(), 99 | cfg: cfg, 100 | codec: codec, 101 | aView: arraymap.NewArrayMap(), 102 | pView: arraymap.NewArrayMap(), 103 | msgBuffer: arraymap.NewArrayMap(), 104 | failmsgBuffer: arraymap.NewArrayMap(), 105 | } 106 | } 107 | 108 | // Serve starts a standalone agent, waiting for 109 | // incoming connections. 110 | func (ag *agent) Serve() error { 111 | ln, err := net.ListenTCP(ag.cfg.Net, ag.cfg.LocalTCPAddr) 112 | if err != nil { 113 | log.Errorf("Serve() Cannot listen %v\n", err) 114 | return err 115 | } 116 | go ag.healLoop() 117 | go ag.shuffleLoop() 118 | ag.ln = ln 119 | ag.serve() 120 | return nil 121 | } 122 | 123 | // serve listens on the TCP listener, waits for incoming connections. 124 | func (ag *agent) serve() { 125 | for { 126 | conn, err := ag.ln.AcceptTCP() 127 | if err != nil { 128 | log.Errorf("Agent.serve(): Failed to accept\n") 129 | continue 130 | } 131 | // TODO(Yifan): Set read time ount. 132 | go ag.serveConn(conn, nil) 133 | } 134 | } 135 | 136 | // serveConn() serves a connection. 137 | func (ag *agent) serveConn(conn *net.TCPConn, node *node.Node) { 138 | for { 139 | msg, err := ag.codec.ReadMsg(conn) 140 | if err != nil { 141 | //log.Errorf("Agent.serveConn(): Failed to decode message: %v\n", err) 142 | ag.replaceActiveNode(node) 143 | return 144 | } 145 | // Dispatch messages. 146 | switch t := msg.(type) { 147 | case *message.Join: 148 | ag.handleJoin(conn, msg.(*message.Join)) 149 | case *message.Neighbor: 150 | ag.handleNeighbor(conn, msg.(*message.Neighbor)) 151 | case *message.ForwardJoin: 152 | ag.handleForwardJoin(msg.(*message.ForwardJoin)) 153 | case *message.Disconnect: 154 | ag.handleDisconnect(msg.(*message.Disconnect)) 155 | case *message.Shuffle: 156 | ag.handleShuffle(msg.(*message.Shuffle)) 157 | case *message.ShuffleReply: 158 | ag.handleShuffleReply(msg.(*message.ShuffleReply)) 159 | case *message.UserMessage: 160 | ag.handleUserMessage(msg.(*message.UserMessage)) 161 | default: 162 | log.Errorf("Agent.serveConn(): Unexpected message type: %T\n", t) 163 | ag.replaceActiveNode(node) 164 | return 165 | } 166 | } 167 | } 168 | 169 | func (ag *agent) healLoop() { 170 | tick := time.Tick(time.Duration(ag.cfg.HealDuration) * time.Second) 171 | for { 172 | select { 173 | case <-tick: 174 | ag.aView.Lock() 175 | ag.pView.Lock() 176 | if ag.aView.Len() < ag.cfg.AViewMinSize { 177 | if ag.pView.Len() > 0 { 178 | nd := chooseRandomNode(ag.pView, 0) 179 | ag.neighbor(nd, message.Neighbor_Low) 180 | } 181 | } 182 | ag.aView.Unlock() 183 | ag.pView.Unlock() 184 | } 185 | } 186 | } 187 | 188 | func (ag *agent) shuffleLoop() { 189 | tick := time.Tick(time.Duration(ag.cfg.ShuffleDuration) * time.Second) 190 | for { 191 | select { 192 | case <-tick: 193 | ag.aView.RLock() 194 | ag.pView.RLock() 195 | if ag.aView.Len() == 0 { 196 | ag.aView.RUnlock() 197 | ag.pView.RUnlock() 198 | continue 199 | } 200 | node := chooseRandomNode(ag.aView, 0) 201 | if node == nil { 202 | continue 203 | } 204 | list := ag.makeShuffleList() 205 | ag.aView.RUnlock() 206 | ag.pView.RUnlock() 207 | go ag.shuffle(node, list) 208 | } 209 | } 210 | } 211 | 212 | func (ag *agent) makeShuffleList() []*message.Candidate { 213 | candidates := make([]*message.Candidate, 0, 1+ag.cfg.Ka+ag.cfg.Kp) 214 | self := &message.Candidate{ 215 | Id: proto.Uint64(ag.id), 216 | Addr: proto.String(ag.cfg.AddrStr), 217 | } 218 | candidates = append(candidates, self) 219 | candidates = append(candidates, chooseRandomCandidates(ag.aView, ag.cfg.Ka)...) 220 | candidates = append(candidates, chooseRandomCandidates(ag.pView, ag.cfg.Kp)...) 221 | return candidates 222 | } 223 | 224 | // addNodeActiveView() adds the node to the active view. If 225 | // the active view is full, it will move one node from the active 226 | // view to the passive view before adding the node. 227 | // If the passive view is also full, it will drop a random node 228 | // in the passive view. 229 | func (ag *agent) addNodeActiveView(node *node.Node) { 230 | if node.Id == ag.id { 231 | return 232 | } 233 | if ag.aView.Has(node.Id) { 234 | return 235 | } 236 | if ag.aView.Len() == ag.cfg.AViewMaxSize { 237 | n := chooseRandomNode(ag.aView, 0) 238 | go ag.disconnect(n) 239 | ag.aView.Remove(n.Id) 240 | ag.addNodePassiveView(n) 241 | } 242 | ag.aView.Append(node.Id, node) 243 | } 244 | 245 | // addNodePassiveView() adds a node to the passive view. If 246 | // the passive view is full, it will drop a random node. 247 | func (ag *agent) addNodePassiveView(node *node.Node) { 248 | if node.Id == ag.id { 249 | return 250 | } 251 | if ag.aView.Has(node.Id) { 252 | return 253 | } 254 | if ag.pView.Has(node.Id) { 255 | return 256 | } 257 | if ag.pView.Len() == ag.cfg.PViewSize { 258 | n := chooseRandomNode(ag.pView, 0) 259 | ag.pView.Remove(n.Id) 260 | } 261 | ag.pView.Append(node.Id, node) 262 | } 263 | 264 | // replaceActiveNode() replaces a "dead" node in the active 265 | // view with a node randomly chosen from the passive view. 266 | func (ag *agent) replaceActiveNode(node *node.Node) { 267 | if node == nil { 268 | /* The listening socket. */ 269 | return 270 | } 271 | ag.aView.Lock() 272 | ag.pView.Lock() 273 | defer ag.aView.Unlock() 274 | defer ag.pView.Unlock() 275 | 276 | if !ag.aView.Has(node.Id) { 277 | /* It's voluntarily disconnected. */ 278 | return 279 | } 280 | 281 | // TODO add the node to passive view instead of removing. 282 | ag.aView.Remove(node.Id) 283 | node.Conn.Close() 284 | 285 | nd := chooseRandomNode(ag.pView, 0) 286 | if nd == nil { 287 | log.Warningf("No nodes in passive view\n") 288 | if ag.aView.Len() > 0 { 289 | // TODO aggressively shuffle. 290 | return 291 | } 292 | log.Warningf("Lost all peers! Join again\n") 293 | 294 | ag.aView.Unlock() 295 | ag.pView.Unlock() 296 | err := ag.Join(ag.cfg.ShufflePeers()...) 297 | ag.aView.Lock() 298 | ag.pView.Lock() 299 | 300 | if err != nil { 301 | log.Warningf("No available peers, need a new list!") 302 | return 303 | } 304 | return 305 | } 306 | ag.pView.Remove(nd.Id) 307 | ag.neighbor(nd, message.Neighbor_Low) 308 | // We need at least one active node. 309 | for ag.aView.Len() == 0 { 310 | nd = chooseRandomNode(ag.pView, 0) 311 | if nd == nil { 312 | log.Warningf("Lost all peers! Join again\n") 313 | 314 | ag.aView.Unlock() 315 | ag.pView.Unlock() 316 | err := ag.Join(ag.cfg.ShufflePeers()...) 317 | ag.aView.Lock() 318 | ag.pView.Lock() 319 | 320 | if err != nil { 321 | log.Warningf("No available peers, need a new list!") 322 | return 323 | } 324 | return 325 | } 326 | ag.pView.Remove(nd.Id) 327 | ag.neighbor(nd, message.Neighbor_High) 328 | } 329 | ag.resendFailedMessages() 330 | } 331 | 332 | // Resend failed messages if any. 333 | // NOTE: The view locks should already be held when invoking this function. 334 | func (ag *agent) resendFailedMessages() { 335 | 336 | // Should not use defer unlock to prevent deadlock, 337 | // because in userMessage() we will probably lock again. 338 | ag.failmsgBuffer.Lock() 339 | values := ag.failmsgBuffer.Values() 340 | ag.failmsgBuffer.RemoveAll() 341 | ag.failmsgBuffer.Unlock() 342 | 343 | // We have already lock the view, so do not need locks here. 344 | for _, v := range values { 345 | log.Debugf("Resending message %v\n", v) 346 | msg := v.(*message.UserMessage) 347 | for _, vv := range ag.aView.Values() { 348 | nd := vv.(*node.Node) 349 | go ag.userMessage(nd, msg) 350 | } 351 | } 352 | return 353 | } 354 | 355 | // handleJoin() handles Join message. If it accepts the request, it will add 356 | // the node in the active view. As specified by the protocol, a node should 357 | // always accept Join requests. 358 | func (ag *agent) handleJoin(conn *net.TCPConn, msg *message.Join) { 359 | newNode := &node.Node{ 360 | Id: msg.GetId(), 361 | Addr: msg.GetAddr(), 362 | Conn: conn, 363 | } 364 | 365 | ag.aView.Lock() 366 | ag.pView.Lock() 367 | defer ag.aView.Unlock() 368 | defer ag.pView.Unlock() 369 | 370 | if newNode.Id != ag.id { 371 | ag.addNodeActiveView(newNode) 372 | go ag.serveConn(newNode.Conn, newNode) 373 | go ag.acceptJoin(newNode) 374 | 375 | } else { 376 | go ag.rejectJoin(newNode) 377 | } 378 | 379 | // Send ForwardJoin message to all other the nodes in the active view. 380 | for _, v := range ag.aView.Values() { 381 | nd := v.(*node.Node) 382 | if nd == newNode { 383 | continue 384 | } 385 | go ag.forwardJoin(nd, newNode, uint32(rand.Intn(ag.cfg.ARWL))) 386 | } 387 | } 388 | 389 | // handleNeighbor() handles Neighbor message. If the request is high priority, 390 | // the receiver will always accept the request and add the node to its active view. 391 | // If the request is low priority, then the request will only be accepted when 392 | // there are empty slot in the active view. 393 | func (ag *agent) handleNeighbor(conn *net.TCPConn, msg *message.Neighbor) { 394 | newNode := &node.Node{ 395 | Id: msg.GetId(), 396 | Addr: msg.GetAddr(), 397 | Conn: conn, 398 | } 399 | 400 | ag.aView.Lock() 401 | ag.pView.Lock() 402 | defer ag.aView.Unlock() 403 | defer ag.pView.Unlock() 404 | 405 | if ag.aView.Len() == ag.cfg.AViewMaxSize { 406 | if msg.GetPriority() == message.Neighbor_Low { 407 | go ag.rejectNeighbor(newNode) 408 | // TODO(yifan): Add the node to passive view. 409 | return 410 | } 411 | } 412 | ag.addNodeActiveView(newNode) 413 | go ag.serveConn(newNode.Conn, newNode) 414 | go ag.acceptNeighbor(newNode) 415 | return 416 | } 417 | 418 | // handleForwardJoin() handles the ForwardJoin message, and decides whether 419 | // it will add the original sender to the active view or passive view. 420 | func (ag *agent) handleForwardJoin(msg *message.ForwardJoin) { 421 | ttl := msg.GetTtl() 422 | newNode := &node.Node{ 423 | Id: msg.GetSourceId(), 424 | Addr: msg.GetSourceAddr(), 425 | } 426 | 427 | ag.aView.Lock() 428 | ag.pView.Lock() 429 | defer ag.aView.Unlock() 430 | defer ag.pView.Unlock() 431 | 432 | if ttl == 0 || ag.aView.Len() <= 1 { // TODO(yifan): Loose this? 433 | if ag.id != newNode.Id && !ag.aView.Has(newNode.Id) { 434 | ag.neighbor(newNode, message.Neighbor_High) 435 | } 436 | return 437 | } 438 | if ttl == uint32(ag.cfg.PRWL) { 439 | ag.addNodePassiveView(newNode) 440 | } 441 | node := chooseRandomNode(ag.aView, msg.GetId()) 442 | go ag.forwardJoin(node, newNode, ttl-1) 443 | return 444 | } 445 | 446 | // handleDisconnect() handles Disconnect message. It will replace the node 447 | // with another node from the passive view. And send Neighbor message to it. 448 | func (ag *agent) handleDisconnect(msg *message.Disconnect) { 449 | id := msg.GetId() 450 | 451 | ag.aView.RLock() 452 | if !ag.aView.Has(id) { 453 | ag.aView.RUnlock() 454 | return 455 | } 456 | nd := ag.aView.GetValueOf(id).(*node.Node) 457 | ag.aView.RUnlock() 458 | ag.replaceActiveNode(nd) 459 | return 460 | } 461 | 462 | // handleShuffle() handles Shuffle message. It will send back a ShuffleReply 463 | // message and update it's views. 464 | func (ag *agent) handleShuffle(msg *message.Shuffle) { 465 | ag.aView.Lock() 466 | ag.pView.Lock() 467 | defer ag.aView.Unlock() 468 | defer ag.pView.Unlock() 469 | 470 | ttl := msg.GetTtl() 471 | if ttl > 0 && ag.pView.Len() > 1 { 472 | node := chooseRandomNode(ag.aView, msg.GetId()) 473 | msg.Ttl = proto.Uint32(ttl - 1) 474 | go ag.forwardShuffle(node, msg) 475 | return 476 | } 477 | candidates := msg.GetCandidates() 478 | replyCandidates := chooseRandomCandidates(ag.aView, ag.cfg.Ka) 479 | replyCandidates = append(replyCandidates, chooseRandomCandidates(ag.pView, ag.cfg.Kp)...) 480 | go ag.shuffleReply(msg, replyCandidates) 481 | for _, candidate := range candidates { 482 | node := &node.Node{ 483 | Id: candidate.GetId(), 484 | Addr: candidate.GetAddr(), 485 | } 486 | ag.addNodePassiveView(node) 487 | } 488 | return 489 | } 490 | 491 | // handleShuffleReply() handles ShuffleReply message. It will update it's views. 492 | func (ag *agent) handleShuffleReply(msg *message.ShuffleReply) { 493 | ag.aView.Lock() 494 | ag.pView.Lock() 495 | defer ag.aView.Unlock() 496 | defer ag.pView.Unlock() 497 | 498 | candidates := msg.GetCandidates() 499 | for _, candidate := range candidates { 500 | node := &node.Node{ 501 | Id: candidate.GetId(), 502 | Addr: candidate.GetAddr(), 503 | } 504 | ag.addNodePassiveView(node) 505 | } 506 | return 507 | } 508 | 509 | // handleUserMessage() handles user defined messages. It will forward the message 510 | // to the nodes in its active view. 511 | func (ag *agent) handleUserMessage(msg *message.UserMessage) { 512 | // Test if the message is stale. 513 | ms, err := time.ParseDuration("1ms") 514 | if err != nil { 515 | panic("failed to parse duration") // Shouldn't happen. 516 | } 517 | deadline := msg.GetTs() + ms.Nanoseconds()*int64(ag.cfg.MLife) 518 | now := time.Now().UnixNano() 519 | if now >= deadline { 520 | log.Debugf("Message is too old, deadline: %v, now %v\n", deadline, now) 521 | return 522 | } 523 | 524 | // Test if the message has been already received. 525 | hash := hashMessage(msg.GetPayload()) 526 | 527 | ag.msgBuffer.Lock() 528 | defer ag.msgBuffer.Unlock() 529 | 530 | if ag.msgBuffer.Has(hash) { 531 | purgeDeadline := ag.msgBuffer.GetValueOf(hash) 532 | if purgeDeadline.(int64) >= now { 533 | log.Debugf("Message is alread received, and with purge deadline, hash: %v\n", hash) 534 | return 535 | } 536 | ag.msgBuffer.Remove(hash) 537 | } 538 | 539 | purgeDeadline := now + ms.Nanoseconds()*int64(ag.cfg.PurgeDuration) 540 | ag.msgBuffer.Append(hash, purgeDeadline) 541 | 542 | // Invoke user's message handler. 543 | go ag.msgHandler(msg.GetPayload()) 544 | 545 | ag.aView.Lock() 546 | defer ag.aView.Unlock() 547 | 548 | for _, v := range ag.aView.Values() { 549 | nd := v.(*node.Node) 550 | go ag.userMessage(nd, msg) 551 | } 552 | return 553 | } 554 | 555 | // Join joins the node to the cluster by contacting the nodes provied in the 556 | // list. 557 | func (ag *agent) Join(peerAddrs ...string) error { 558 | // Append the peer list. 559 | ag.cfg.Peers = append(ag.cfg.Peers, peerAddrs...) 560 | 561 | for _, peerAddr := range peerAddrs { 562 | tcpAddr, err := net.ResolveTCPAddr(ag.cfg.Net, peerAddr) 563 | if err != nil { 564 | log.Errorf("Agent.Join(): Failed to ResolveTCPAddr: %v\n", err) 565 | continue 566 | } 567 | node := &node.Node{Addr: peerAddr} 568 | 569 | log.Infof("Agent.Join(): Trying to join %s...\n", peerAddr) 570 | conn, err := net.DialTCP(ag.cfg.Net, nil, tcpAddr) 571 | if err != nil { 572 | log.Errorf("Agent.Join(): Failed to dial %s: %v\n", peerAddr, err) 573 | continue 574 | } 575 | node.Conn = conn 576 | accepted, err := ag.join(node) 577 | if !accepted || err != nil { 578 | log.Errorf("Agent.Join(): Failed to join: accepted:%v, err:%v\n", accepted, err) 579 | continue 580 | } 581 | // Successfully Joined. 582 | log.Infof("Successfully join node %s\n", peerAddr) 583 | return nil 584 | } 585 | return ErrNoAvailablePeers 586 | } 587 | 588 | // Leave causes the agent to leave the cluster. 589 | func (ag *agent) Leave() { 590 | log.Infof("Agent is leaving...\n") 591 | os.Exit(0) 592 | } 593 | 594 | // Broadcast broadcasts a message to the cluster. 595 | func (ag *agent) Broadcast(payload []byte) error { 596 | msg := &message.UserMessage{ 597 | Id: proto.Uint64(ag.id), 598 | Payload: payload, 599 | Ts: proto.Int64(time.Now().UnixNano()), 600 | } 601 | 602 | ag.aView.Lock() 603 | defer ag.aView.Unlock() 604 | for _, v := range ag.aView.Values() { 605 | nd := v.(*node.Node) 606 | ag.userMessage(nd, msg) 607 | } 608 | return nil 609 | } 610 | 611 | // RegisterMessageHandler registers a user provided message callback 612 | // to handle messages. 613 | func (ag *agent) RegisterMessageHandler(mh MessageHandler) { 614 | ag.msgHandler = mh 615 | } 616 | 617 | // List() lists the active view and passive view. 618 | func (ag *agent) List() ([]byte, error) { 619 | ag.aView.Lock() 620 | ag.pView.Lock() 621 | defer ag.aView.Unlock() 622 | defer ag.pView.Unlock() 623 | 624 | log.Debugf("AView:\n") 625 | for _, v := range ag.aView.Values() { 626 | log.Debugf("%v\n", v.(*node.Node)) 627 | } 628 | log.Debugf("PView:\n") 629 | for _, v := range ag.pView.Values() { 630 | log.Debugf("%v\n", v.(*node.Node)) 631 | } 632 | 633 | view := &view{ag.aView, ag.pView} 634 | return json.Marshal(view) 635 | } 636 | 637 | // Helpers 638 | 639 | // hashMessage() returns the hash of a user message. 640 | func hashMessage(msg []byte) [sha1.Size]byte { 641 | return sha1.Sum(msg) 642 | } 643 | 644 | // chooseRandomNode() chooses a random node from the active view 645 | // or passive view. 646 | func chooseRandomNode(view *arraymap.ArrayMap, excludeId uint64) *node.Node { 647 | if view.Len() == 0 { 648 | return nil 649 | } 650 | index := rand.Intn(view.Len()) 651 | nd := view.GetValueAt(index).(*node.Node) 652 | if nd.Id == excludeId { 653 | if view.Len() == 1 { 654 | return nil 655 | } 656 | nd = view.GetValueAt((index + 1) % view.Len()).(*node.Node) 657 | } 658 | return nd 659 | } 660 | 661 | // chooseRandomCandidates() selects n random nodes from the active view 662 | // or passive view. If n > the size of the view, then all nodes are returned. 663 | func chooseRandomCandidates(view *arraymap.ArrayMap, n int) []*message.Candidate { 664 | if view.Len() == 0 { 665 | return nil 666 | } 667 | if n >= view.Len() { 668 | n = view.Len() 669 | } 670 | candidates := make([]*message.Candidate, n) 671 | index := rand.Intn(view.Len()) 672 | for i := 0; i < n; i++ { 673 | nd := view.GetValueAt((index + i) % view.Len()).(*node.Node) 674 | candidates[i] = &message.Candidate{ 675 | Id: proto.Uint64(nd.Id), 676 | Addr: proto.String(nd.Addr), 677 | } 678 | } 679 | return candidates 680 | } 681 | -------------------------------------------------------------------------------- /agent/agent_msg.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | 7 | "github.com/go-distributed/gog/message" 8 | "github.com/go-distributed/gog/node" 9 | 10 | "code.google.com/p/gogoprotobuf/proto" 11 | ) 12 | 13 | var ( 14 | ErrInvalidMessageType = errors.New("Invalid message type") 15 | ErrNoAvailablePeers = errors.New("No available peers") 16 | ) 17 | 18 | // disconnect() sends a Disconnect message to the node and close the connection. 19 | // TODO(yifan): cache the connection. 20 | func (ag *agent) disconnect(node *node.Node) { 21 | msg := &message.Disconnect{Id: proto.Uint64(ag.id)} 22 | ag.codec.WriteMsg(msg, node.Conn) // TODO record err log. 23 | node.Conn.Close() 24 | } 25 | 26 | // forwardJoin() sends a ForwardJoin message to the node. The message 27 | // will include the Id and Addr of the source node, as the receiver might 28 | // use these information to establish a connection. 29 | func (ag *agent) forwardJoin(node, newNode *node.Node, ttl uint32) { 30 | msg := &message.ForwardJoin{ 31 | Id: proto.Uint64(ag.id), 32 | SourceId: proto.Uint64(newNode.Id), 33 | SourceAddr: proto.String(newNode.Addr), 34 | Ttl: proto.Uint32(ttl), 35 | } 36 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 37 | node.Conn.Close() 38 | } 39 | } 40 | 41 | // rejectNeighbor() sends a the NeighborReply with accept = false. 42 | func (ag *agent) rejectNeighbor(node *node.Node) { 43 | msg := &message.NeighborReply{ 44 | Id: proto.Uint64(ag.id), 45 | Accept: proto.Bool(false), 46 | } 47 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 48 | // TODO log 49 | } 50 | } 51 | 52 | // acceptNeighbor() sends a the NeighborReply with accept = true. 53 | func (ag *agent) acceptNeighbor(node *node.Node) { 54 | msg := &message.NeighborReply{ 55 | Id: proto.Uint64(ag.id), 56 | Accept: proto.Bool(true), 57 | } 58 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 59 | node.Conn.Close() 60 | } 61 | } 62 | 63 | func (ag *agent) join(node *node.Node) (bool, error) { 64 | msg := &message.Join{ 65 | Id: proto.Uint64(ag.id), 66 | Addr: proto.String(ag.cfg.AddrStr), 67 | } 68 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 69 | node.Conn.Close() 70 | return false, err 71 | } 72 | recvMsg, err := ag.codec.ReadMsg(node.Conn) 73 | if err != nil { 74 | // TODO(yifan) log. 75 | node.Conn.Close() 76 | return false, err 77 | } 78 | reply, ok := recvMsg.(*message.JoinReply) 79 | if !ok { 80 | node.Conn.Close() 81 | return false, ErrInvalidMessageType 82 | } 83 | id, accepted := reply.GetId(), reply.GetAccept() 84 | node.Id = id 85 | 86 | if accepted { 87 | ag.aView.Lock() 88 | ag.pView.Lock() 89 | defer ag.aView.Unlock() 90 | defer ag.pView.Unlock() 91 | 92 | ag.addNodeActiveView(node) 93 | go ag.serveConn(node.Conn, node) 94 | } 95 | return accepted, nil 96 | } 97 | 98 | func (ag *agent) acceptJoin(node *node.Node) error { 99 | msg := &message.JoinReply{ 100 | Id: proto.Uint64(ag.id), 101 | Accept: proto.Bool(true), 102 | } 103 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 104 | node.Conn.Close() 105 | return err 106 | } 107 | return nil 108 | } 109 | 110 | func (ag *agent) rejectJoin(node *node.Node) error { 111 | defer node.Conn.Close() 112 | msg := &message.JoinReply{ 113 | Id: proto.Uint64(ag.id), 114 | Accept: proto.Bool(false), 115 | } 116 | 117 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 118 | return err 119 | } 120 | return nil 121 | } 122 | 123 | // neighbor() sends a Neighbor message, and wait for the reply. 124 | // If the other side accepts the request, we add the node to the active view. 125 | func (ag *agent) neighbor(node *node.Node, priority message.Neighbor_Priority) (bool, error) { 126 | ag.aView.Unlock() 127 | ag.pView.Unlock() 128 | defer ag.aView.Lock() 129 | defer ag.pView.Lock() 130 | 131 | addr, err := net.ResolveTCPAddr(ag.cfg.Net, node.Addr) 132 | if err != nil { 133 | // TODO(yifan) log. 134 | return false, err 135 | } 136 | conn, err := net.DialTCP(ag.cfg.Net, nil, addr) 137 | if err != nil { 138 | // TODO(yifan) log. 139 | return false, err 140 | } 141 | node.Conn = conn 142 | 143 | msg := &message.Neighbor{ 144 | Id: proto.Uint64(ag.id), 145 | Addr: proto.String(ag.cfg.AddrStr), 146 | Priority: priority.Enum(), 147 | } 148 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 149 | // TODO(yifan) log. 150 | node.Conn.Close() 151 | return false, err 152 | } 153 | recvMsg, err := ag.codec.ReadMsg(node.Conn) 154 | if err != nil { 155 | // TODO(yifan) log. 156 | node.Conn.Close() 157 | return false, err 158 | } 159 | reply, ok := recvMsg.(*message.NeighborReply) 160 | if !ok { 161 | node.Conn.Close() 162 | return false, ErrInvalidMessageType 163 | } 164 | 165 | accepted := reply.GetAccept() 166 | 167 | ag.aView.Lock() 168 | ag.pView.Lock() 169 | if accepted { 170 | ag.addNodeActiveView(node) 171 | go ag.serveConn(node.Conn, node) 172 | } else { 173 | ag.addNodePassiveView(node) 174 | } 175 | ag.aView.Unlock() 176 | ag.pView.Unlock() 177 | 178 | return accepted, nil 179 | } 180 | 181 | // userMessage() sends a user message to the node. 182 | func (ag *agent) userMessage(node *node.Node, msg proto.Message) { 183 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 184 | // Record this message, so we can resend it later. 185 | umsg := msg.(*message.UserMessage) 186 | hash := hashMessage(umsg.GetPayload()) 187 | 188 | ag.failmsgBuffer.Lock() 189 | ag.failmsgBuffer.Append(hash, msg) 190 | ag.failmsgBuffer.Unlock() 191 | 192 | node.Conn.Close() 193 | } 194 | } 195 | 196 | func (ag *agent) forwardShuffle(node *node.Node, msg *message.Shuffle) { 197 | msg.Id = proto.Uint64(ag.id) 198 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 199 | node.Conn.Close() 200 | } 201 | } 202 | 203 | func (ag *agent) shuffleReply(msg *message.Shuffle, candidates []*message.Candidate) error { 204 | // TODO use existing tcp. 205 | addr, err := net.ResolveTCPAddr(ag.cfg.Net, msg.GetAddr()) 206 | if err != nil { 207 | // TODO(yifan) log 208 | return err 209 | } 210 | conn, err := net.DialTCP(ag.cfg.Net, nil, addr) 211 | if err != nil { 212 | return err 213 | } 214 | reply := &message.ShuffleReply{ 215 | Id: proto.Uint64(ag.id), 216 | Candidates: candidates, 217 | } 218 | if err := ag.codec.WriteMsg(reply, conn); err != nil { 219 | // TODO log 220 | return err 221 | } 222 | conn.Close() 223 | return nil 224 | } 225 | 226 | func (ag *agent) shuffle(node *node.Node, candidates []*message.Candidate) { 227 | msg := &message.Shuffle{ 228 | Id: proto.Uint64(ag.id), 229 | SourceId: proto.Uint64(ag.id), 230 | Addr: proto.String(ag.cfg.AddrStr), 231 | Candidates: candidates, 232 | Ttl: proto.Uint32(uint32(ag.cfg.SRWL)), 233 | } 234 | if err := ag.codec.WriteMsg(msg, node.Conn); err != nil { 235 | node.Conn.Close() 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /arraymap/arraymap.go: -------------------------------------------------------------------------------- 1 | package arraymap 2 | 3 | import ( 4 | "encoding/json" 5 | "sync" 6 | ) 7 | 8 | type ArrayMap struct { 9 | positions map[interface{}]int 10 | keys []interface{} 11 | values []interface{} 12 | rwl sync.RWMutex 13 | } 14 | 15 | func NewArrayMap() *ArrayMap { 16 | return &ArrayMap{ 17 | positions: make(map[interface{}]int), 18 | keys: make([]interface{}, 0), 19 | values: make([]interface{}, 0), 20 | } 21 | } 22 | 23 | func (a *ArrayMap) Len() int { 24 | return len(a.keys) 25 | } 26 | 27 | func (a *ArrayMap) Append(key, value interface{}) { 28 | if _, existed := a.positions[key]; existed { 29 | return 30 | } 31 | a.keys = append(a.keys, key) 32 | a.values = append(a.values, value) 33 | a.positions[key] = len(a.keys) - 1 34 | } 35 | 36 | func (a *ArrayMap) GetKeyAt(i int) interface{} { 37 | return a.keys[i] 38 | } 39 | 40 | func (a *ArrayMap) GetValueAt(i int) interface{} { 41 | return a.values[i] 42 | } 43 | 44 | func (a *ArrayMap) GetValueOf(key interface{}) interface{} { 45 | return a.values[a.positions[key]] 46 | } 47 | 48 | func (a *ArrayMap) Has(key interface{}) bool { 49 | _, existed := a.positions[key] 50 | return existed 51 | } 52 | 53 | func (a *ArrayMap) RemoveAt(i int) { 54 | removingKey, lastKey := a.keys[i], a.keys[len(a.keys)-1] 55 | // Swap the removing item and the last. 56 | a.keys[i], a.keys[len(a.keys)-1] = a.keys[len(a.keys)-1], a.keys[i] 57 | a.values[i], a.values[len(a.values)-1] = a.values[len(a.values)-1], a.values[i] 58 | 59 | // Update the position. 60 | a.positions[lastKey] = i 61 | 62 | // Removing. 63 | a.keys = a.keys[:len(a.keys)-1] 64 | a.values = a.values[:len(a.values)-1] 65 | delete(a.positions, removingKey) 66 | } 67 | 68 | func (a *ArrayMap) Remove(key interface{}) { 69 | if _, exisited := a.positions[key]; exisited { 70 | a.RemoveAt(a.positions[key]) 71 | } 72 | } 73 | 74 | func (a *ArrayMap) RemoveAll() { 75 | for k := range a.positions { 76 | delete(a.positions, k) 77 | } 78 | a.keys = a.keys[:0] 79 | a.values = a.values[:0] 80 | } 81 | 82 | func (a *ArrayMap) Lock() { 83 | a.rwl.Lock() 84 | return 85 | } 86 | 87 | func (a *ArrayMap) Unlock() { 88 | a.rwl.Unlock() 89 | return 90 | } 91 | 92 | func (a *ArrayMap) RLock() { 93 | a.rwl.RLock() 94 | return 95 | } 96 | 97 | func (a *ArrayMap) RUnlock() { 98 | a.rwl.RUnlock() 99 | return 100 | } 101 | 102 | func (a *ArrayMap) Values() []interface{} { 103 | return a.values 104 | } 105 | 106 | func (a *ArrayMap) MarshalJSON() ([]byte, error) { 107 | return json.Marshal(a.values) 108 | } 109 | -------------------------------------------------------------------------------- /arraymap/arraymap_test.go: -------------------------------------------------------------------------------- 1 | package arraymap 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/go-distributed/testify/assert" 7 | ) 8 | 9 | func TestSimple(t *testing.T) { 10 | am := NewArrayMap() 11 | for i := 0; i < 42; i++ { 12 | am.Append("foo", "bar") 13 | } 14 | assert.Equal(t, 1, am.Len()) 15 | am.Append("bar", "foo") 16 | assert.Equal(t, 2, am.Len()) 17 | 18 | am.Append("hello", "world") 19 | assert.Equal(t, 3, am.Len()) 20 | 21 | am.Append("world", "hello") 22 | assert.Equal(t, 4, am.Len()) 23 | 24 | assert.Equal(t, "foo", am.GetKeyAt(0)) 25 | assert.Equal(t, "bar", am.GetKeyAt(1)) 26 | assert.Equal(t, "hello", am.GetKeyAt(2)) 27 | assert.Equal(t, "world", am.GetKeyAt(3)) 28 | 29 | assert.Equal(t, "bar", am.GetValueAt(0)) 30 | assert.Equal(t, "foo", am.GetValueAt(1)) 31 | assert.Equal(t, "world", am.GetValueAt(2)) 32 | assert.Equal(t, "hello", am.GetValueAt(3)) 33 | 34 | assert.True(t, am.Has("foo")) 35 | assert.True(t, am.Has("bar")) 36 | assert.True(t, am.Has("hello")) 37 | assert.True(t, am.Has("world")) 38 | 39 | assert.False(t, am.Has("good")) 40 | 41 | assert.Panics(t, func() { am.RemoveAt(10) }) 42 | am.RemoveAt(2) 43 | assert.False(t, am.Has("hello")) 44 | assert.Equal(t, 3, am.Len()) 45 | assert.Equal(t, 3, len(am.positions)) 46 | assert.Equal(t, 3, len(am.keys)) 47 | assert.Equal(t, 3, len(am.values)) 48 | 49 | assert.Equal(t, "world", am.GetKeyAt(2)) 50 | assert.Equal(t, "hello", am.GetValueAt(2)) 51 | am.RemoveAt(0) 52 | assert.Equal(t, "world", am.GetKeyAt(0)) 53 | assert.Equal(t, "hello", am.GetValueAt(0)) 54 | am.RemoveAt(0) 55 | assert.Equal(t, "bar", am.GetKeyAt(0)) 56 | assert.Equal(t, "foo", am.GetValueAt(0)) 57 | am.Remove("bar") 58 | assert.Panics(t, func() { am.RemoveAt(0) }) 59 | am.Remove("aaaa") 60 | 61 | assert.Equal(t, 0, am.Len()) 62 | assert.Equal(t, 0, len(am.positions)) 63 | assert.Equal(t, 0, len(am.keys)) 64 | assert.Equal(t, 0, len(am.values)) 65 | } 66 | -------------------------------------------------------------------------------- /codec/codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "errors" 7 | "fmt" 8 | "io" 9 | "net" 10 | "reflect" 11 | 12 | "code.google.com/p/gogoprotobuf/proto" 13 | 14 | log "github.com/go-distributed/gog/log" // DEBUG 15 | ) 16 | 17 | const ( 18 | sizeOfUint8 = 1 19 | sizeOfInt32 = 4 20 | ) 21 | 22 | var ( 23 | ErrMessageAlreadyRegistered = errors.New("Message already registered") 24 | ErrMessageNotRegistered = errors.New("Message not registered") 25 | ErrCannotWriteMessage = errors.New("Cannot write message") 26 | ) 27 | 28 | // Codec describes the codec interface, 29 | // which encodes/decodes protobuf messages from/to 30 | // an io.Reader/Writer 31 | type Codec interface { 32 | // Register registers a message so that the 33 | // codec can identify the message when reading 34 | // the TCP connection. 35 | Register(msg proto.Message) 36 | // WriteMsg encodes a message to bytes and 37 | // writes it to the io.Writer 38 | WriteMsg(msg proto.Message, w io.Writer) error 39 | // ReadMsg reads bytes from the io.Reader 40 | // and decodes it to a message. 41 | ReadMsg(r io.Reader) (proto.Message, error) 42 | } 43 | 44 | // ProtobufCodec implements the codec interface. 45 | type ProtobufCodec struct { 46 | // registeredMessages is a map from message indices 47 | // to message types. The indices increase monotonically. 48 | registeredMessages map[uint8]reflect.Type 49 | // messageIndices is a map from message types 50 | // to message indices. 51 | messageIndices map[reflect.Type]uint8 52 | } 53 | 54 | // NewProtobufCodec creates and returns a ProtobufCodec. 55 | func NewProtobufCodec() *ProtobufCodec { 56 | return &ProtobufCodec{ 57 | registeredMessages: make(map[uint8]reflect.Type), 58 | messageIndices: make(map[reflect.Type]uint8), 59 | } 60 | } 61 | 62 | // Register registers a message. Note this is not concurrent-safe. 63 | func (pc *ProtobufCodec) Register(msg proto.Message) { 64 | mtype := reflect.TypeOf(msg) 65 | if _, existed := pc.messageIndices[mtype]; existed { 66 | panic("Message already registered") 67 | } 68 | index := uint8(len(pc.messageIndices)) 69 | pc.messageIndices[mtype] = index 70 | pc.registeredMessages[index] = mtype 71 | return 72 | } 73 | 74 | // WriteMsg encodes a message to bytes and writes it to the io.Writer. 75 | func (pc *ProtobufCodec) WriteMsg(msg proto.Message, w io.Writer) error { 76 | log.Debugf("Send:%v, to:%v\n", msg, w.(*net.TCPConn).RemoteAddr()) 77 | index, existed := pc.messageIndices[reflect.TypeOf(msg)] 78 | if !existed { 79 | return ErrMessageNotRegistered 80 | } 81 | buf := new(bytes.Buffer) 82 | 83 | // Encode. 84 | b, err := proto.Marshal(msg) 85 | if err != nil { 86 | return err 87 | } 88 | // Write the length. 89 | if err := binary.Write(buf, binary.LittleEndian, int32(len(b)+sizeOfUint8)); err != nil { 90 | return err 91 | } 92 | // Write the type. 93 | if err := binary.Write(buf, binary.LittleEndian, index); err != nil { 94 | return err 95 | } 96 | // Write the bytes. 97 | buf.Write(b) 98 | if _, err = buf.WriteTo(w); err != nil { 99 | return err 100 | } 101 | return nil 102 | } 103 | 104 | // ReadMsg reads bytes from an io.Reader and decode it to a message. 105 | func (pc *ProtobufCodec) ReadMsg(r io.Reader) (msg proto.Message, err error) { 106 | var length int32 107 | 108 | defer func() { 109 | if fatal := recover(); fatal != nil { 110 | err = fmt.Errorf("Recovery from panic: %v", fatal) 111 | log.Errorf(err.Error()) 112 | } 113 | }() 114 | 115 | // Read the length. 116 | if err = binary.Read(r, binary.LittleEndian, &length); err != nil { 117 | return nil, err 118 | } 119 | b := make([]byte, length) 120 | // Read the type and bytes. 121 | if _, err = io.ReadFull(r, b); err != nil { 122 | return nil, err 123 | } 124 | // Get the index. 125 | index := uint8(b[0]) 126 | // Decode. 127 | mtype, existed := pc.registeredMessages[index] 128 | if !existed { 129 | return nil, ErrMessageNotRegistered 130 | } 131 | msg = reflect.New(mtype.Elem()).Interface().(proto.Message) 132 | if err := proto.Unmarshal(b[1:], msg); err != nil { 133 | return nil, err 134 | } 135 | log.Debugf("Recv:%v, from:%v\n", msg, r.(*net.TCPConn).RemoteAddr()) 136 | return msg, nil 137 | } 138 | -------------------------------------------------------------------------------- /codec/codec_test.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/rand" 7 | "testing" 8 | 9 | "code.google.com/p/gogoprotobuf/proto" 10 | "github.com/go-distributed/gog/message" 11 | "github.com/go-distributed/testify/assert" 12 | ) 13 | 14 | const nsInOneSecond = 1000000000 // 10^9 15 | var payload []byte 16 | 17 | func genRandomMessage(length int) []byte { 18 | b := make([]byte, length) 19 | for i := range b { 20 | b[i] = byte(rand.Int()) 21 | } 22 | return b 23 | } 24 | 25 | func TestRegister(t *testing.T) { 26 | umsg := &message.UserMessage{ 27 | Id: proto.String("localhost:8080"), 28 | Payload: []byte("hello world"), 29 | } 30 | pc := NewProtobufCodec() 31 | pc.Register(umsg) 32 | assert.Panics(t, func() { pc.Register(umsg) }) 33 | } 34 | 35 | func TestWriteMsgReadMsg(t *testing.T) { 36 | umsg1 := &message.UserMessage{ 37 | Id: proto.String("localhost:8080"), 38 | Payload: []byte("hello"), 39 | } 40 | umsg2 := &message.UserMessage{ 41 | Id: proto.String("localhost:8080"), 42 | Payload: []byte("world"), 43 | } 44 | pc := NewProtobufCodec() 45 | pc.Register(umsg1) 46 | rw := new(bytes.Buffer) 47 | assert.NoError(t, pc.WriteMsg(umsg1, rw)) 48 | assert.NoError(t, pc.WriteMsg(umsg2, rw)) 49 | msg1, err := pc.ReadMsg(rw) 50 | msg2, err := pc.ReadMsg(rw) 51 | assert.NoError(t, err) 52 | assert.Equal(t, umsg1, msg1) 53 | assert.Equal(t, umsg2, msg2) 54 | } 55 | 56 | func BenchmarkWriteMsgReadMsg(b *testing.B) { 57 | umsg := &message.UserMessage{ 58 | Id: proto.String("localhost:8080"), 59 | Payload: payload, 60 | } 61 | pc := NewProtobufCodec() 62 | pc.Register(umsg) 63 | rw := new(bytes.Buffer) 64 | 65 | for i := 0; i < b.N; i++ { 66 | assert.NoError(b, pc.WriteMsg(umsg, rw)) 67 | _, err := pc.ReadMsg(rw) 68 | assert.NoError(b, err) 69 | } 70 | } 71 | 72 | func TestWriteMsgReadMsgThroughput(t *testing.T) { 73 | var result testing.BenchmarkResult 74 | 75 | fmt.Println("Small Message Payload (100 bytes)") 76 | payload = genRandomMessage(100) 77 | result = testing.Benchmark(BenchmarkWriteMsgReadMsg) 78 | fmt.Println(result.N, " ", result.NsPerOp(), "ns/op") 79 | fmt.Println("Throughput:", nsInOneSecond/result.NsPerOp()*10*10/1024/1024, "MB/s") 80 | 81 | fmt.Println("Medium Message Payload (1000 bytes)") 82 | payload = genRandomMessage(1000) 83 | result = testing.Benchmark(BenchmarkWriteMsgReadMsg) 84 | fmt.Println(result.N, " ", result.NsPerOp(), "ns/op") 85 | fmt.Println("Throughput:", nsInOneSecond/result.NsPerOp()*100*100/1024/1024, "MB/s") 86 | 87 | fmt.Println("Large Message Payload (1000*1000 bytes ~1m)") 88 | payload = genRandomMessage(1000 * 1000) 89 | result = testing.Benchmark(BenchmarkWriteMsgReadMsg) 90 | fmt.Println(result.N, " ", result.NsPerOp(), "ns/op") 91 | fmt.Println("Throughput:", nsInOneSecond/result.NsPerOp()*1000*1000/1024/1024, "MB/s") 92 | 93 | } 94 | -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "io/ioutil" 7 | "math/rand" 8 | "net" 9 | "os" 10 | "os/exec" 11 | "strings" 12 | ) 13 | 14 | // Config describes the config of the system. 15 | type Config struct { 16 | // Net should be tcp4 or tcp6. 17 | Net string `json:"net"` 18 | // AddrStr is the local address string. 19 | AddrStr string `json:"address"` 20 | // Peers is peer list. 21 | Peers []string `json:"-"` 22 | // LocalTCPAddr is TCP address parsed from 23 | // Net and AddrStr. 24 | LocalTCPAddr *net.TCPAddr `json:"-"` 25 | // AViewMinSize is the minimum size of the active view. 26 | AViewMinSize int `json:"active_view_min"` 27 | // AViewMaxSize is the maximum size of the active view. 28 | AViewMaxSize int `json:"active_view_max"` 29 | // PViewSize is the size of the passive view. 30 | PViewSize int `json:"passive_view"` 31 | // Ka is the number of nodes to choose from active view 32 | // when shuffling views. 33 | Ka int `json:"ka"` 34 | // Kp is the number of nodes to choose from passive view 35 | // when shuffling views. 36 | Kp int `json:"kb"` 37 | // Active Random Walk Length. 38 | ARWL int `json:"arwl"` 39 | // Passive Random Walk Length. 40 | PRWL int `json:"prwl"` 41 | // Shuffle Random Walk Length. 42 | SRWL int `json:"srwl"` 43 | // Message life. 44 | MLife int `json:"message_life"` 45 | // Shuffle Duration in seconds. 46 | ShuffleDuration int `json:"shuffle_duration"` 47 | // Heal Duration in seconds. 48 | HealDuration int `json:"heal_duration"` 49 | // The REST server address. 50 | RESTAddrStr string `json:"rest_addr"` 51 | // The path to user message handler(script). 52 | UserMsgHandler string `json:"user_message_handler"` 53 | // The duration to purge message buffer. 54 | PurgeDuration int `json:"purge_duration"` 55 | } 56 | 57 | func ParseConfig() (*Config, error) { 58 | var peerStr string 59 | var peerFile string 60 | 61 | cfg := new(Config) 62 | 63 | flag.StringVar(&cfg.Net, "net", "tcp", "The network protocol") 64 | flag.StringVar(&cfg.AddrStr, "addr", ":8424", "The address the agent listens on") 65 | 66 | flag.StringVar(&peerFile, "peer-file", "", "Peer list file") 67 | flag.StringVar(&peerStr, "peers", "", "Comma-separated list of peers") 68 | 69 | flag.IntVar(&cfg.AViewMinSize, "min-aview-size", 3, "The minimum size of the active view") 70 | flag.IntVar(&cfg.AViewMaxSize, "max-aview-size", 5, "The maximum size of the active view") 71 | flag.IntVar(&cfg.PViewSize, "pview-size", 5, "The size of the passive view") 72 | 73 | flag.IntVar(&cfg.Ka, "ka", 1, "The number of active nodes to shuffle") 74 | flag.IntVar(&cfg.Kp, "kp", 3, "The number of passive nodes to shuffle") 75 | 76 | flag.IntVar(&cfg.ARWL, "arwl", 5, "The active random walk length") 77 | flag.IntVar(&cfg.PRWL, "prwl", 5, "The passive random walk length") 78 | flag.IntVar(&cfg.SRWL, "srwl", 5, "The shuffle random walk length") 79 | 80 | flag.IntVar(&cfg.MLife, "msg-life", 5000, "The default message life (milliseconds)") 81 | flag.IntVar(&cfg.ShuffleDuration, "shuffle-duration", 5, "The default shuffle duration (seconds)") 82 | flag.IntVar(&cfg.HealDuration, "heal", 1, "The default heal duration (seconds)") 83 | flag.StringVar(&cfg.RESTAddrStr, "rest-addr", ":9424", "The address of the REST server") 84 | flag.StringVar(&cfg.UserMsgHandler, "user-message-handler", "", "The path to the user message handler script") 85 | flag.IntVar(&cfg.PurgeDuration, "purge-duration", 5000, "The default purge duration (milliseconds)") 86 | 87 | flag.Parse() 88 | 89 | // Check configuration. 90 | if peerStr != "" { 91 | cfg.Peers = strings.Split(peerStr, ",") 92 | } 93 | if peerFile != "" { 94 | peers, err := parsePeerFile(peerFile) 95 | if err != nil { 96 | return nil, err 97 | } 98 | cfg.Peers = peers 99 | } 100 | 101 | // Check agent server address. 102 | tcpAddr, err := net.ResolveTCPAddr(cfg.Net, cfg.AddrStr) 103 | if err != nil { 104 | return nil, err 105 | } 106 | cfg.LocalTCPAddr = tcpAddr 107 | 108 | // Check REST API address. 109 | _, err = net.ResolveTCPAddr(cfg.Net, cfg.RESTAddrStr) 110 | if err != nil { 111 | return nil, err 112 | } 113 | 114 | // Check User Message Handler. 115 | if cfg.UserMsgHandler != "" { 116 | _, err = exec.LookPath(cfg.UserMsgHandler) 117 | if err != nil { 118 | return nil, err 119 | } 120 | } 121 | return cfg, nil 122 | } 123 | 124 | func parsePeerFile(path string) ([]string, error) { 125 | var peers []string 126 | f, err := os.Open(path) 127 | if err != nil { 128 | return nil, err 129 | } 130 | defer f.Close() 131 | 132 | b, err := ioutil.ReadAll(f) 133 | if err != nil { 134 | return nil, err 135 | } 136 | if err := json.Unmarshal(b, &peers); err != nil { 137 | return nil, err 138 | } 139 | return peers, nil 140 | } 141 | 142 | func (cfg *Config) ShufflePeers() []string { 143 | shuffledPeers := make([]string, len(cfg.Peers)) 144 | copy(shuffledPeers, cfg.Peers) 145 | for i := range shuffledPeers { 146 | if i == 0 { 147 | continue 148 | } 149 | swapIndex := rand.Intn(i) 150 | shuffledPeers[i], shuffledPeers[swapIndex] = shuffledPeers[swapIndex], shuffledPeers[i] 151 | } 152 | return shuffledPeers 153 | } 154 | -------------------------------------------------------------------------------- /log/logger.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | const ( 10 | verboseError = iota 11 | verboseWarning 12 | verboseInfo 13 | verboseDebug 14 | ) 15 | 16 | var verbose int 17 | 18 | func init() { 19 | flag.IntVar(&verbose, "v", verboseDebug, "The log veboseness") 20 | } 21 | 22 | func Errorf(format string, args ...interface{}) { 23 | if verbose < verboseError { 24 | return 25 | } 26 | fmt.Fprintf(os.Stderr, "[ERROR]: ") 27 | fmt.Fprintf(os.Stderr, format, args...) 28 | } 29 | 30 | func Fatalf(format string, args ...interface{}) { 31 | if verbose < verboseError { 32 | return 33 | } 34 | fmt.Fprintf(os.Stderr, "[FATAL]: ") 35 | fmt.Fprintf(os.Stderr, format, args...) 36 | os.Exit(1) 37 | } 38 | 39 | func Warningf(format string, args ...interface{}) { 40 | if verbose < verboseWarning { 41 | return 42 | } 43 | fmt.Fprintf(os.Stderr, "[WARNING]: ") 44 | fmt.Fprintf(os.Stderr, format, args...) 45 | } 46 | 47 | func Infof(format string, args ...interface{}) { 48 | if verbose < verboseInfo { 49 | return 50 | } 51 | fmt.Fprintf(os.Stderr, "[INFO]: ") 52 | fmt.Fprintf(os.Stderr, format, args...) 53 | } 54 | 55 | func Debugf(format string, args ...interface{}) { 56 | if verbose < verboseDebug { 57 | return 58 | } 59 | fmt.Fprintf(os.Stderr, "[DEBUG]: ") 60 | fmt.Fprintf(os.Stderr, format, args...) 61 | } 62 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/go-distributed/gog/config" 5 | "github.com/go-distributed/gog/log" 6 | "github.com/go-distributed/gog/rest" 7 | ) 8 | 9 | func main() { 10 | cfg, err := config.ParseConfig() 11 | if err != nil { 12 | log.Fatalf("Failed to parse configuration: %v\n", err) 13 | } 14 | 15 | srv := rest.NewServer(cfg) 16 | log.Infof("Starting server...\n") 17 | if err := srv.ListenAndServe(); err != nil { 18 | log.Fatalf("Failed to start server: %v\n", err) 19 | } 20 | return 21 | } 22 | -------------------------------------------------------------------------------- /message/Makefile: -------------------------------------------------------------------------------- 1 | all: message.proto 2 | protoc --proto_path=${GOPATH}/src:${GOPATH}/src/code.google.com/p/gogoprotobuf/protobuf:. --gogo_out=. message.proto 3 | -------------------------------------------------------------------------------- /message/message.proto: -------------------------------------------------------------------------------- 1 | package message; 2 | 3 | import "code.google.com/p/gogoprotobuf/gogoproto/gogo.proto"; 4 | 5 | option (gogoproto.gostring_all) = true; 6 | option (gogoproto.equal_all) = true; 7 | option (gogoproto.verbose_equal_all) = true; 8 | option (gogoproto.goproto_stringer_all) = false; 9 | option (gogoproto.stringer_all) = true; 10 | option (gogoproto.populate_all) = true; 11 | option (gogoproto.testgen_all) = true; 12 | option (gogoproto.benchgen_all) = true; 13 | option (gogoproto.marshaler_all) = true; 14 | option (gogoproto.sizer_all) = true; 15 | option (gogoproto.unmarshaler_all) = true; 16 | 17 | // User defined messages. 18 | message UserMessage { 19 | required uint64 id = 1; 20 | optional bytes payload = 2; 21 | required int64 ts = 3; // Millisecond. 22 | } 23 | 24 | // The Join request. 25 | message Join { 26 | required uint64 id = 1; 27 | required string addr = 2; 28 | } 29 | 30 | // The Join reply. 31 | message JoinReply { 32 | required uint64 id = 1; 33 | required bool accept = 2; 34 | } 35 | 36 | // The Neighbor request. 37 | message Neighbor { 38 | required uint64 id = 1; 39 | enum Priority { 40 | Low = 0; 41 | High = 1; 42 | } 43 | required string addr = 2; 44 | required Priority priority = 3; 45 | } 46 | 47 | // The reply to Neighbor request. 48 | message NeighborReply { 49 | required uint64 id = 1; 50 | required bool accept = 2; 51 | } 52 | 53 | // The ForwardJoin request. 54 | message ForwardJoin { 55 | required uint64 id = 1; 56 | required uint64 sourceId = 2; 57 | required string sourceAddr = 3; 58 | required uint32 ttl = 4; 59 | // Maybe add a nounce here to avoid 60 | // fake reply. 61 | } 62 | 63 | // The Disconnect request. 64 | message Disconnect { 65 | required uint64 id = 1; 66 | } 67 | 68 | // The Candidate. 69 | message Candidate { 70 | required uint64 id = 1; 71 | required string addr = 2; 72 | } 73 | 74 | // The Shuffle request. 75 | message Shuffle { 76 | required uint64 id = 1; 77 | required uint64 sourceId = 2; 78 | required string addr = 3; 79 | repeated Candidate candidates = 4; 80 | required uint32 ttl = 5; 81 | } 82 | 83 | // The ShuffleReply. 84 | message ShuffleReply { 85 | required uint64 id = 1; 86 | repeated Candidate candidates = 2; 87 | } 88 | -------------------------------------------------------------------------------- /message/messagepb_test.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. 2 | // source: message.proto 3 | // DO NOT EDIT! 4 | 5 | /* 6 | Package message is a generated protocol buffer package. 7 | 8 | It is generated from these files: 9 | message.proto 10 | 11 | It has these top-level messages: 12 | UserMessage 13 | Join 14 | JoinReply 15 | Neighbor 16 | NeighborReply 17 | ForwardJoin 18 | Disconnect 19 | Candidate 20 | Shuffle 21 | ShuffleReply 22 | */ 23 | package message 24 | 25 | import testing "testing" 26 | import math_rand "math/rand" 27 | import time "time" 28 | import code_google_com_p_gogoprotobuf_proto "code.google.com/p/gogoprotobuf/proto" 29 | import testing1 "testing" 30 | import math_rand1 "math/rand" 31 | import time1 "time" 32 | import encoding_json "encoding/json" 33 | import testing2 "testing" 34 | import math_rand2 "math/rand" 35 | import time2 "time" 36 | import code_google_com_p_gogoprotobuf_proto1 "code.google.com/p/gogoprotobuf/proto" 37 | import math_rand3 "math/rand" 38 | import time3 "time" 39 | import testing3 "testing" 40 | import fmt "fmt" 41 | import math_rand4 "math/rand" 42 | import time4 "time" 43 | import testing4 "testing" 44 | import code_google_com_p_gogoprotobuf_proto2 "code.google.com/p/gogoprotobuf/proto" 45 | import math_rand5 "math/rand" 46 | import time5 "time" 47 | import testing5 "testing" 48 | import fmt1 "fmt" 49 | import go_parser "go/parser" 50 | import math_rand6 "math/rand" 51 | import time6 "time" 52 | import testing6 "testing" 53 | import code_google_com_p_gogoprotobuf_proto3 "code.google.com/p/gogoprotobuf/proto" 54 | 55 | func TestUserMessageProto(t *testing.T) { 56 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 57 | p := NewPopulatedUserMessage(popr, false) 58 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 59 | if err != nil { 60 | panic(err) 61 | } 62 | msg := &UserMessage{} 63 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 64 | panic(err) 65 | } 66 | for i := range data { 67 | data[i] = byte(popr.Intn(256)) 68 | } 69 | if err := p.VerboseEqual(msg); err != nil { 70 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 71 | } 72 | if !p.Equal(msg) { 73 | t.Fatalf("%#v !Proto %#v", msg, p) 74 | } 75 | } 76 | 77 | func TestUserMessageMarshalTo(t *testing.T) { 78 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 79 | p := NewPopulatedUserMessage(popr, false) 80 | size := p.Size() 81 | data := make([]byte, size) 82 | for i := range data { 83 | data[i] = byte(popr.Intn(256)) 84 | } 85 | _, err := p.MarshalTo(data) 86 | if err != nil { 87 | panic(err) 88 | } 89 | msg := &UserMessage{} 90 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 91 | panic(err) 92 | } 93 | for i := range data { 94 | data[i] = byte(popr.Intn(256)) 95 | } 96 | if err := p.VerboseEqual(msg); err != nil { 97 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 98 | } 99 | if !p.Equal(msg) { 100 | t.Fatalf("%#v !Proto %#v", msg, p) 101 | } 102 | } 103 | 104 | func BenchmarkUserMessageProtoMarshal(b *testing.B) { 105 | popr := math_rand.New(math_rand.NewSource(616)) 106 | total := 0 107 | pops := make([]*UserMessage, 10000) 108 | for i := 0; i < 10000; i++ { 109 | pops[i] = NewPopulatedUserMessage(popr, false) 110 | } 111 | b.ResetTimer() 112 | for i := 0; i < b.N; i++ { 113 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 114 | if err != nil { 115 | panic(err) 116 | } 117 | total += len(data) 118 | } 119 | b.SetBytes(int64(total / b.N)) 120 | } 121 | 122 | func BenchmarkUserMessageProtoUnmarshal(b *testing.B) { 123 | popr := math_rand.New(math_rand.NewSource(616)) 124 | total := 0 125 | datas := make([][]byte, 10000) 126 | for i := 0; i < 10000; i++ { 127 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedUserMessage(popr, false)) 128 | if err != nil { 129 | panic(err) 130 | } 131 | datas[i] = data 132 | } 133 | msg := &UserMessage{} 134 | b.ResetTimer() 135 | for i := 0; i < b.N; i++ { 136 | total += len(datas[i%10000]) 137 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 138 | panic(err) 139 | } 140 | } 141 | b.SetBytes(int64(total / b.N)) 142 | } 143 | 144 | func TestJoinProto(t *testing.T) { 145 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 146 | p := NewPopulatedJoin(popr, false) 147 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 148 | if err != nil { 149 | panic(err) 150 | } 151 | msg := &Join{} 152 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 153 | panic(err) 154 | } 155 | for i := range data { 156 | data[i] = byte(popr.Intn(256)) 157 | } 158 | if err := p.VerboseEqual(msg); err != nil { 159 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 160 | } 161 | if !p.Equal(msg) { 162 | t.Fatalf("%#v !Proto %#v", msg, p) 163 | } 164 | } 165 | 166 | func TestJoinMarshalTo(t *testing.T) { 167 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 168 | p := NewPopulatedJoin(popr, false) 169 | size := p.Size() 170 | data := make([]byte, size) 171 | for i := range data { 172 | data[i] = byte(popr.Intn(256)) 173 | } 174 | _, err := p.MarshalTo(data) 175 | if err != nil { 176 | panic(err) 177 | } 178 | msg := &Join{} 179 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 180 | panic(err) 181 | } 182 | for i := range data { 183 | data[i] = byte(popr.Intn(256)) 184 | } 185 | if err := p.VerboseEqual(msg); err != nil { 186 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 187 | } 188 | if !p.Equal(msg) { 189 | t.Fatalf("%#v !Proto %#v", msg, p) 190 | } 191 | } 192 | 193 | func BenchmarkJoinProtoMarshal(b *testing.B) { 194 | popr := math_rand.New(math_rand.NewSource(616)) 195 | total := 0 196 | pops := make([]*Join, 10000) 197 | for i := 0; i < 10000; i++ { 198 | pops[i] = NewPopulatedJoin(popr, false) 199 | } 200 | b.ResetTimer() 201 | for i := 0; i < b.N; i++ { 202 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 203 | if err != nil { 204 | panic(err) 205 | } 206 | total += len(data) 207 | } 208 | b.SetBytes(int64(total / b.N)) 209 | } 210 | 211 | func BenchmarkJoinProtoUnmarshal(b *testing.B) { 212 | popr := math_rand.New(math_rand.NewSource(616)) 213 | total := 0 214 | datas := make([][]byte, 10000) 215 | for i := 0; i < 10000; i++ { 216 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedJoin(popr, false)) 217 | if err != nil { 218 | panic(err) 219 | } 220 | datas[i] = data 221 | } 222 | msg := &Join{} 223 | b.ResetTimer() 224 | for i := 0; i < b.N; i++ { 225 | total += len(datas[i%10000]) 226 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 227 | panic(err) 228 | } 229 | } 230 | b.SetBytes(int64(total / b.N)) 231 | } 232 | 233 | func TestJoinReplyProto(t *testing.T) { 234 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 235 | p := NewPopulatedJoinReply(popr, false) 236 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 237 | if err != nil { 238 | panic(err) 239 | } 240 | msg := &JoinReply{} 241 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 242 | panic(err) 243 | } 244 | for i := range data { 245 | data[i] = byte(popr.Intn(256)) 246 | } 247 | if err := p.VerboseEqual(msg); err != nil { 248 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 249 | } 250 | if !p.Equal(msg) { 251 | t.Fatalf("%#v !Proto %#v", msg, p) 252 | } 253 | } 254 | 255 | func TestJoinReplyMarshalTo(t *testing.T) { 256 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 257 | p := NewPopulatedJoinReply(popr, false) 258 | size := p.Size() 259 | data := make([]byte, size) 260 | for i := range data { 261 | data[i] = byte(popr.Intn(256)) 262 | } 263 | _, err := p.MarshalTo(data) 264 | if err != nil { 265 | panic(err) 266 | } 267 | msg := &JoinReply{} 268 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 269 | panic(err) 270 | } 271 | for i := range data { 272 | data[i] = byte(popr.Intn(256)) 273 | } 274 | if err := p.VerboseEqual(msg); err != nil { 275 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 276 | } 277 | if !p.Equal(msg) { 278 | t.Fatalf("%#v !Proto %#v", msg, p) 279 | } 280 | } 281 | 282 | func BenchmarkJoinReplyProtoMarshal(b *testing.B) { 283 | popr := math_rand.New(math_rand.NewSource(616)) 284 | total := 0 285 | pops := make([]*JoinReply, 10000) 286 | for i := 0; i < 10000; i++ { 287 | pops[i] = NewPopulatedJoinReply(popr, false) 288 | } 289 | b.ResetTimer() 290 | for i := 0; i < b.N; i++ { 291 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 292 | if err != nil { 293 | panic(err) 294 | } 295 | total += len(data) 296 | } 297 | b.SetBytes(int64(total / b.N)) 298 | } 299 | 300 | func BenchmarkJoinReplyProtoUnmarshal(b *testing.B) { 301 | popr := math_rand.New(math_rand.NewSource(616)) 302 | total := 0 303 | datas := make([][]byte, 10000) 304 | for i := 0; i < 10000; i++ { 305 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedJoinReply(popr, false)) 306 | if err != nil { 307 | panic(err) 308 | } 309 | datas[i] = data 310 | } 311 | msg := &JoinReply{} 312 | b.ResetTimer() 313 | for i := 0; i < b.N; i++ { 314 | total += len(datas[i%10000]) 315 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 316 | panic(err) 317 | } 318 | } 319 | b.SetBytes(int64(total / b.N)) 320 | } 321 | 322 | func TestNeighborProto(t *testing.T) { 323 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 324 | p := NewPopulatedNeighbor(popr, false) 325 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 326 | if err != nil { 327 | panic(err) 328 | } 329 | msg := &Neighbor{} 330 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 331 | panic(err) 332 | } 333 | for i := range data { 334 | data[i] = byte(popr.Intn(256)) 335 | } 336 | if err := p.VerboseEqual(msg); err != nil { 337 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 338 | } 339 | if !p.Equal(msg) { 340 | t.Fatalf("%#v !Proto %#v", msg, p) 341 | } 342 | } 343 | 344 | func TestNeighborMarshalTo(t *testing.T) { 345 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 346 | p := NewPopulatedNeighbor(popr, false) 347 | size := p.Size() 348 | data := make([]byte, size) 349 | for i := range data { 350 | data[i] = byte(popr.Intn(256)) 351 | } 352 | _, err := p.MarshalTo(data) 353 | if err != nil { 354 | panic(err) 355 | } 356 | msg := &Neighbor{} 357 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 358 | panic(err) 359 | } 360 | for i := range data { 361 | data[i] = byte(popr.Intn(256)) 362 | } 363 | if err := p.VerboseEqual(msg); err != nil { 364 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 365 | } 366 | if !p.Equal(msg) { 367 | t.Fatalf("%#v !Proto %#v", msg, p) 368 | } 369 | } 370 | 371 | func BenchmarkNeighborProtoMarshal(b *testing.B) { 372 | popr := math_rand.New(math_rand.NewSource(616)) 373 | total := 0 374 | pops := make([]*Neighbor, 10000) 375 | for i := 0; i < 10000; i++ { 376 | pops[i] = NewPopulatedNeighbor(popr, false) 377 | } 378 | b.ResetTimer() 379 | for i := 0; i < b.N; i++ { 380 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 381 | if err != nil { 382 | panic(err) 383 | } 384 | total += len(data) 385 | } 386 | b.SetBytes(int64(total / b.N)) 387 | } 388 | 389 | func BenchmarkNeighborProtoUnmarshal(b *testing.B) { 390 | popr := math_rand.New(math_rand.NewSource(616)) 391 | total := 0 392 | datas := make([][]byte, 10000) 393 | for i := 0; i < 10000; i++ { 394 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedNeighbor(popr, false)) 395 | if err != nil { 396 | panic(err) 397 | } 398 | datas[i] = data 399 | } 400 | msg := &Neighbor{} 401 | b.ResetTimer() 402 | for i := 0; i < b.N; i++ { 403 | total += len(datas[i%10000]) 404 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 405 | panic(err) 406 | } 407 | } 408 | b.SetBytes(int64(total / b.N)) 409 | } 410 | 411 | func TestNeighborReplyProto(t *testing.T) { 412 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 413 | p := NewPopulatedNeighborReply(popr, false) 414 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 415 | if err != nil { 416 | panic(err) 417 | } 418 | msg := &NeighborReply{} 419 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 420 | panic(err) 421 | } 422 | for i := range data { 423 | data[i] = byte(popr.Intn(256)) 424 | } 425 | if err := p.VerboseEqual(msg); err != nil { 426 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 427 | } 428 | if !p.Equal(msg) { 429 | t.Fatalf("%#v !Proto %#v", msg, p) 430 | } 431 | } 432 | 433 | func TestNeighborReplyMarshalTo(t *testing.T) { 434 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 435 | p := NewPopulatedNeighborReply(popr, false) 436 | size := p.Size() 437 | data := make([]byte, size) 438 | for i := range data { 439 | data[i] = byte(popr.Intn(256)) 440 | } 441 | _, err := p.MarshalTo(data) 442 | if err != nil { 443 | panic(err) 444 | } 445 | msg := &NeighborReply{} 446 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 447 | panic(err) 448 | } 449 | for i := range data { 450 | data[i] = byte(popr.Intn(256)) 451 | } 452 | if err := p.VerboseEqual(msg); err != nil { 453 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 454 | } 455 | if !p.Equal(msg) { 456 | t.Fatalf("%#v !Proto %#v", msg, p) 457 | } 458 | } 459 | 460 | func BenchmarkNeighborReplyProtoMarshal(b *testing.B) { 461 | popr := math_rand.New(math_rand.NewSource(616)) 462 | total := 0 463 | pops := make([]*NeighborReply, 10000) 464 | for i := 0; i < 10000; i++ { 465 | pops[i] = NewPopulatedNeighborReply(popr, false) 466 | } 467 | b.ResetTimer() 468 | for i := 0; i < b.N; i++ { 469 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 470 | if err != nil { 471 | panic(err) 472 | } 473 | total += len(data) 474 | } 475 | b.SetBytes(int64(total / b.N)) 476 | } 477 | 478 | func BenchmarkNeighborReplyProtoUnmarshal(b *testing.B) { 479 | popr := math_rand.New(math_rand.NewSource(616)) 480 | total := 0 481 | datas := make([][]byte, 10000) 482 | for i := 0; i < 10000; i++ { 483 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedNeighborReply(popr, false)) 484 | if err != nil { 485 | panic(err) 486 | } 487 | datas[i] = data 488 | } 489 | msg := &NeighborReply{} 490 | b.ResetTimer() 491 | for i := 0; i < b.N; i++ { 492 | total += len(datas[i%10000]) 493 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 494 | panic(err) 495 | } 496 | } 497 | b.SetBytes(int64(total / b.N)) 498 | } 499 | 500 | func TestForwardJoinProto(t *testing.T) { 501 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 502 | p := NewPopulatedForwardJoin(popr, false) 503 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 504 | if err != nil { 505 | panic(err) 506 | } 507 | msg := &ForwardJoin{} 508 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 509 | panic(err) 510 | } 511 | for i := range data { 512 | data[i] = byte(popr.Intn(256)) 513 | } 514 | if err := p.VerboseEqual(msg); err != nil { 515 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 516 | } 517 | if !p.Equal(msg) { 518 | t.Fatalf("%#v !Proto %#v", msg, p) 519 | } 520 | } 521 | 522 | func TestForwardJoinMarshalTo(t *testing.T) { 523 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 524 | p := NewPopulatedForwardJoin(popr, false) 525 | size := p.Size() 526 | data := make([]byte, size) 527 | for i := range data { 528 | data[i] = byte(popr.Intn(256)) 529 | } 530 | _, err := p.MarshalTo(data) 531 | if err != nil { 532 | panic(err) 533 | } 534 | msg := &ForwardJoin{} 535 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 536 | panic(err) 537 | } 538 | for i := range data { 539 | data[i] = byte(popr.Intn(256)) 540 | } 541 | if err := p.VerboseEqual(msg); err != nil { 542 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 543 | } 544 | if !p.Equal(msg) { 545 | t.Fatalf("%#v !Proto %#v", msg, p) 546 | } 547 | } 548 | 549 | func BenchmarkForwardJoinProtoMarshal(b *testing.B) { 550 | popr := math_rand.New(math_rand.NewSource(616)) 551 | total := 0 552 | pops := make([]*ForwardJoin, 10000) 553 | for i := 0; i < 10000; i++ { 554 | pops[i] = NewPopulatedForwardJoin(popr, false) 555 | } 556 | b.ResetTimer() 557 | for i := 0; i < b.N; i++ { 558 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 559 | if err != nil { 560 | panic(err) 561 | } 562 | total += len(data) 563 | } 564 | b.SetBytes(int64(total / b.N)) 565 | } 566 | 567 | func BenchmarkForwardJoinProtoUnmarshal(b *testing.B) { 568 | popr := math_rand.New(math_rand.NewSource(616)) 569 | total := 0 570 | datas := make([][]byte, 10000) 571 | for i := 0; i < 10000; i++ { 572 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedForwardJoin(popr, false)) 573 | if err != nil { 574 | panic(err) 575 | } 576 | datas[i] = data 577 | } 578 | msg := &ForwardJoin{} 579 | b.ResetTimer() 580 | for i := 0; i < b.N; i++ { 581 | total += len(datas[i%10000]) 582 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 583 | panic(err) 584 | } 585 | } 586 | b.SetBytes(int64(total / b.N)) 587 | } 588 | 589 | func TestDisconnectProto(t *testing.T) { 590 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 591 | p := NewPopulatedDisconnect(popr, false) 592 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 593 | if err != nil { 594 | panic(err) 595 | } 596 | msg := &Disconnect{} 597 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 598 | panic(err) 599 | } 600 | for i := range data { 601 | data[i] = byte(popr.Intn(256)) 602 | } 603 | if err := p.VerboseEqual(msg); err != nil { 604 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 605 | } 606 | if !p.Equal(msg) { 607 | t.Fatalf("%#v !Proto %#v", msg, p) 608 | } 609 | } 610 | 611 | func TestDisconnectMarshalTo(t *testing.T) { 612 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 613 | p := NewPopulatedDisconnect(popr, false) 614 | size := p.Size() 615 | data := make([]byte, size) 616 | for i := range data { 617 | data[i] = byte(popr.Intn(256)) 618 | } 619 | _, err := p.MarshalTo(data) 620 | if err != nil { 621 | panic(err) 622 | } 623 | msg := &Disconnect{} 624 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 625 | panic(err) 626 | } 627 | for i := range data { 628 | data[i] = byte(popr.Intn(256)) 629 | } 630 | if err := p.VerboseEqual(msg); err != nil { 631 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 632 | } 633 | if !p.Equal(msg) { 634 | t.Fatalf("%#v !Proto %#v", msg, p) 635 | } 636 | } 637 | 638 | func BenchmarkDisconnectProtoMarshal(b *testing.B) { 639 | popr := math_rand.New(math_rand.NewSource(616)) 640 | total := 0 641 | pops := make([]*Disconnect, 10000) 642 | for i := 0; i < 10000; i++ { 643 | pops[i] = NewPopulatedDisconnect(popr, false) 644 | } 645 | b.ResetTimer() 646 | for i := 0; i < b.N; i++ { 647 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 648 | if err != nil { 649 | panic(err) 650 | } 651 | total += len(data) 652 | } 653 | b.SetBytes(int64(total / b.N)) 654 | } 655 | 656 | func BenchmarkDisconnectProtoUnmarshal(b *testing.B) { 657 | popr := math_rand.New(math_rand.NewSource(616)) 658 | total := 0 659 | datas := make([][]byte, 10000) 660 | for i := 0; i < 10000; i++ { 661 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedDisconnect(popr, false)) 662 | if err != nil { 663 | panic(err) 664 | } 665 | datas[i] = data 666 | } 667 | msg := &Disconnect{} 668 | b.ResetTimer() 669 | for i := 0; i < b.N; i++ { 670 | total += len(datas[i%10000]) 671 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 672 | panic(err) 673 | } 674 | } 675 | b.SetBytes(int64(total / b.N)) 676 | } 677 | 678 | func TestCandidateProto(t *testing.T) { 679 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 680 | p := NewPopulatedCandidate(popr, false) 681 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 682 | if err != nil { 683 | panic(err) 684 | } 685 | msg := &Candidate{} 686 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 687 | panic(err) 688 | } 689 | for i := range data { 690 | data[i] = byte(popr.Intn(256)) 691 | } 692 | if err := p.VerboseEqual(msg); err != nil { 693 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 694 | } 695 | if !p.Equal(msg) { 696 | t.Fatalf("%#v !Proto %#v", msg, p) 697 | } 698 | } 699 | 700 | func TestCandidateMarshalTo(t *testing.T) { 701 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 702 | p := NewPopulatedCandidate(popr, false) 703 | size := p.Size() 704 | data := make([]byte, size) 705 | for i := range data { 706 | data[i] = byte(popr.Intn(256)) 707 | } 708 | _, err := p.MarshalTo(data) 709 | if err != nil { 710 | panic(err) 711 | } 712 | msg := &Candidate{} 713 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 714 | panic(err) 715 | } 716 | for i := range data { 717 | data[i] = byte(popr.Intn(256)) 718 | } 719 | if err := p.VerboseEqual(msg); err != nil { 720 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 721 | } 722 | if !p.Equal(msg) { 723 | t.Fatalf("%#v !Proto %#v", msg, p) 724 | } 725 | } 726 | 727 | func BenchmarkCandidateProtoMarshal(b *testing.B) { 728 | popr := math_rand.New(math_rand.NewSource(616)) 729 | total := 0 730 | pops := make([]*Candidate, 10000) 731 | for i := 0; i < 10000; i++ { 732 | pops[i] = NewPopulatedCandidate(popr, false) 733 | } 734 | b.ResetTimer() 735 | for i := 0; i < b.N; i++ { 736 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 737 | if err != nil { 738 | panic(err) 739 | } 740 | total += len(data) 741 | } 742 | b.SetBytes(int64(total / b.N)) 743 | } 744 | 745 | func BenchmarkCandidateProtoUnmarshal(b *testing.B) { 746 | popr := math_rand.New(math_rand.NewSource(616)) 747 | total := 0 748 | datas := make([][]byte, 10000) 749 | for i := 0; i < 10000; i++ { 750 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedCandidate(popr, false)) 751 | if err != nil { 752 | panic(err) 753 | } 754 | datas[i] = data 755 | } 756 | msg := &Candidate{} 757 | b.ResetTimer() 758 | for i := 0; i < b.N; i++ { 759 | total += len(datas[i%10000]) 760 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 761 | panic(err) 762 | } 763 | } 764 | b.SetBytes(int64(total / b.N)) 765 | } 766 | 767 | func TestShuffleProto(t *testing.T) { 768 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 769 | p := NewPopulatedShuffle(popr, false) 770 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 771 | if err != nil { 772 | panic(err) 773 | } 774 | msg := &Shuffle{} 775 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 776 | panic(err) 777 | } 778 | for i := range data { 779 | data[i] = byte(popr.Intn(256)) 780 | } 781 | if err := p.VerboseEqual(msg); err != nil { 782 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 783 | } 784 | if !p.Equal(msg) { 785 | t.Fatalf("%#v !Proto %#v", msg, p) 786 | } 787 | } 788 | 789 | func TestShuffleMarshalTo(t *testing.T) { 790 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 791 | p := NewPopulatedShuffle(popr, false) 792 | size := p.Size() 793 | data := make([]byte, size) 794 | for i := range data { 795 | data[i] = byte(popr.Intn(256)) 796 | } 797 | _, err := p.MarshalTo(data) 798 | if err != nil { 799 | panic(err) 800 | } 801 | msg := &Shuffle{} 802 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 803 | panic(err) 804 | } 805 | for i := range data { 806 | data[i] = byte(popr.Intn(256)) 807 | } 808 | if err := p.VerboseEqual(msg); err != nil { 809 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 810 | } 811 | if !p.Equal(msg) { 812 | t.Fatalf("%#v !Proto %#v", msg, p) 813 | } 814 | } 815 | 816 | func BenchmarkShuffleProtoMarshal(b *testing.B) { 817 | popr := math_rand.New(math_rand.NewSource(616)) 818 | total := 0 819 | pops := make([]*Shuffle, 10000) 820 | for i := 0; i < 10000; i++ { 821 | pops[i] = NewPopulatedShuffle(popr, false) 822 | } 823 | b.ResetTimer() 824 | for i := 0; i < b.N; i++ { 825 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 826 | if err != nil { 827 | panic(err) 828 | } 829 | total += len(data) 830 | } 831 | b.SetBytes(int64(total / b.N)) 832 | } 833 | 834 | func BenchmarkShuffleProtoUnmarshal(b *testing.B) { 835 | popr := math_rand.New(math_rand.NewSource(616)) 836 | total := 0 837 | datas := make([][]byte, 10000) 838 | for i := 0; i < 10000; i++ { 839 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedShuffle(popr, false)) 840 | if err != nil { 841 | panic(err) 842 | } 843 | datas[i] = data 844 | } 845 | msg := &Shuffle{} 846 | b.ResetTimer() 847 | for i := 0; i < b.N; i++ { 848 | total += len(datas[i%10000]) 849 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 850 | panic(err) 851 | } 852 | } 853 | b.SetBytes(int64(total / b.N)) 854 | } 855 | 856 | func TestShuffleReplyProto(t *testing.T) { 857 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 858 | p := NewPopulatedShuffleReply(popr, false) 859 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(p) 860 | if err != nil { 861 | panic(err) 862 | } 863 | msg := &ShuffleReply{} 864 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 865 | panic(err) 866 | } 867 | for i := range data { 868 | data[i] = byte(popr.Intn(256)) 869 | } 870 | if err := p.VerboseEqual(msg); err != nil { 871 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 872 | } 873 | if !p.Equal(msg) { 874 | t.Fatalf("%#v !Proto %#v", msg, p) 875 | } 876 | } 877 | 878 | func TestShuffleReplyMarshalTo(t *testing.T) { 879 | popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 880 | p := NewPopulatedShuffleReply(popr, false) 881 | size := p.Size() 882 | data := make([]byte, size) 883 | for i := range data { 884 | data[i] = byte(popr.Intn(256)) 885 | } 886 | _, err := p.MarshalTo(data) 887 | if err != nil { 888 | panic(err) 889 | } 890 | msg := &ShuffleReply{} 891 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(data, msg); err != nil { 892 | panic(err) 893 | } 894 | for i := range data { 895 | data[i] = byte(popr.Intn(256)) 896 | } 897 | if err := p.VerboseEqual(msg); err != nil { 898 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 899 | } 900 | if !p.Equal(msg) { 901 | t.Fatalf("%#v !Proto %#v", msg, p) 902 | } 903 | } 904 | 905 | func BenchmarkShuffleReplyProtoMarshal(b *testing.B) { 906 | popr := math_rand.New(math_rand.NewSource(616)) 907 | total := 0 908 | pops := make([]*ShuffleReply, 10000) 909 | for i := 0; i < 10000; i++ { 910 | pops[i] = NewPopulatedShuffleReply(popr, false) 911 | } 912 | b.ResetTimer() 913 | for i := 0; i < b.N; i++ { 914 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(pops[i%10000]) 915 | if err != nil { 916 | panic(err) 917 | } 918 | total += len(data) 919 | } 920 | b.SetBytes(int64(total / b.N)) 921 | } 922 | 923 | func BenchmarkShuffleReplyProtoUnmarshal(b *testing.B) { 924 | popr := math_rand.New(math_rand.NewSource(616)) 925 | total := 0 926 | datas := make([][]byte, 10000) 927 | for i := 0; i < 10000; i++ { 928 | data, err := code_google_com_p_gogoprotobuf_proto.Marshal(NewPopulatedShuffleReply(popr, false)) 929 | if err != nil { 930 | panic(err) 931 | } 932 | datas[i] = data 933 | } 934 | msg := &ShuffleReply{} 935 | b.ResetTimer() 936 | for i := 0; i < b.N; i++ { 937 | total += len(datas[i%10000]) 938 | if err := code_google_com_p_gogoprotobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 939 | panic(err) 940 | } 941 | } 942 | b.SetBytes(int64(total / b.N)) 943 | } 944 | 945 | func TestUserMessageJSON(t *testing1.T) { 946 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 947 | p := NewPopulatedUserMessage(popr, true) 948 | jsondata, err := encoding_json.Marshal(p) 949 | if err != nil { 950 | panic(err) 951 | } 952 | msg := &UserMessage{} 953 | err = encoding_json.Unmarshal(jsondata, msg) 954 | if err != nil { 955 | panic(err) 956 | } 957 | if err := p.VerboseEqual(msg); err != nil { 958 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 959 | } 960 | if !p.Equal(msg) { 961 | t.Fatalf("%#v !Json Equal %#v", msg, p) 962 | } 963 | } 964 | func TestJoinJSON(t *testing1.T) { 965 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 966 | p := NewPopulatedJoin(popr, true) 967 | jsondata, err := encoding_json.Marshal(p) 968 | if err != nil { 969 | panic(err) 970 | } 971 | msg := &Join{} 972 | err = encoding_json.Unmarshal(jsondata, msg) 973 | if err != nil { 974 | panic(err) 975 | } 976 | if err := p.VerboseEqual(msg); err != nil { 977 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 978 | } 979 | if !p.Equal(msg) { 980 | t.Fatalf("%#v !Json Equal %#v", msg, p) 981 | } 982 | } 983 | func TestJoinReplyJSON(t *testing1.T) { 984 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 985 | p := NewPopulatedJoinReply(popr, true) 986 | jsondata, err := encoding_json.Marshal(p) 987 | if err != nil { 988 | panic(err) 989 | } 990 | msg := &JoinReply{} 991 | err = encoding_json.Unmarshal(jsondata, msg) 992 | if err != nil { 993 | panic(err) 994 | } 995 | if err := p.VerboseEqual(msg); err != nil { 996 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 997 | } 998 | if !p.Equal(msg) { 999 | t.Fatalf("%#v !Json Equal %#v", msg, p) 1000 | } 1001 | } 1002 | func TestNeighborJSON(t *testing1.T) { 1003 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 1004 | p := NewPopulatedNeighbor(popr, true) 1005 | jsondata, err := encoding_json.Marshal(p) 1006 | if err != nil { 1007 | panic(err) 1008 | } 1009 | msg := &Neighbor{} 1010 | err = encoding_json.Unmarshal(jsondata, msg) 1011 | if err != nil { 1012 | panic(err) 1013 | } 1014 | if err := p.VerboseEqual(msg); err != nil { 1015 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1016 | } 1017 | if !p.Equal(msg) { 1018 | t.Fatalf("%#v !Json Equal %#v", msg, p) 1019 | } 1020 | } 1021 | func TestNeighborReplyJSON(t *testing1.T) { 1022 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 1023 | p := NewPopulatedNeighborReply(popr, true) 1024 | jsondata, err := encoding_json.Marshal(p) 1025 | if err != nil { 1026 | panic(err) 1027 | } 1028 | msg := &NeighborReply{} 1029 | err = encoding_json.Unmarshal(jsondata, msg) 1030 | if err != nil { 1031 | panic(err) 1032 | } 1033 | if err := p.VerboseEqual(msg); err != nil { 1034 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1035 | } 1036 | if !p.Equal(msg) { 1037 | t.Fatalf("%#v !Json Equal %#v", msg, p) 1038 | } 1039 | } 1040 | func TestForwardJoinJSON(t *testing1.T) { 1041 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 1042 | p := NewPopulatedForwardJoin(popr, true) 1043 | jsondata, err := encoding_json.Marshal(p) 1044 | if err != nil { 1045 | panic(err) 1046 | } 1047 | msg := &ForwardJoin{} 1048 | err = encoding_json.Unmarshal(jsondata, msg) 1049 | if err != nil { 1050 | panic(err) 1051 | } 1052 | if err := p.VerboseEqual(msg); err != nil { 1053 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1054 | } 1055 | if !p.Equal(msg) { 1056 | t.Fatalf("%#v !Json Equal %#v", msg, p) 1057 | } 1058 | } 1059 | func TestDisconnectJSON(t *testing1.T) { 1060 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 1061 | p := NewPopulatedDisconnect(popr, true) 1062 | jsondata, err := encoding_json.Marshal(p) 1063 | if err != nil { 1064 | panic(err) 1065 | } 1066 | msg := &Disconnect{} 1067 | err = encoding_json.Unmarshal(jsondata, msg) 1068 | if err != nil { 1069 | panic(err) 1070 | } 1071 | if err := p.VerboseEqual(msg); err != nil { 1072 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1073 | } 1074 | if !p.Equal(msg) { 1075 | t.Fatalf("%#v !Json Equal %#v", msg, p) 1076 | } 1077 | } 1078 | func TestCandidateJSON(t *testing1.T) { 1079 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 1080 | p := NewPopulatedCandidate(popr, true) 1081 | jsondata, err := encoding_json.Marshal(p) 1082 | if err != nil { 1083 | panic(err) 1084 | } 1085 | msg := &Candidate{} 1086 | err = encoding_json.Unmarshal(jsondata, msg) 1087 | if err != nil { 1088 | panic(err) 1089 | } 1090 | if err := p.VerboseEqual(msg); err != nil { 1091 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1092 | } 1093 | if !p.Equal(msg) { 1094 | t.Fatalf("%#v !Json Equal %#v", msg, p) 1095 | } 1096 | } 1097 | func TestShuffleJSON(t *testing1.T) { 1098 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 1099 | p := NewPopulatedShuffle(popr, true) 1100 | jsondata, err := encoding_json.Marshal(p) 1101 | if err != nil { 1102 | panic(err) 1103 | } 1104 | msg := &Shuffle{} 1105 | err = encoding_json.Unmarshal(jsondata, msg) 1106 | if err != nil { 1107 | panic(err) 1108 | } 1109 | if err := p.VerboseEqual(msg); err != nil { 1110 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1111 | } 1112 | if !p.Equal(msg) { 1113 | t.Fatalf("%#v !Json Equal %#v", msg, p) 1114 | } 1115 | } 1116 | func TestShuffleReplyJSON(t *testing1.T) { 1117 | popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 1118 | p := NewPopulatedShuffleReply(popr, true) 1119 | jsondata, err := encoding_json.Marshal(p) 1120 | if err != nil { 1121 | panic(err) 1122 | } 1123 | msg := &ShuffleReply{} 1124 | err = encoding_json.Unmarshal(jsondata, msg) 1125 | if err != nil { 1126 | panic(err) 1127 | } 1128 | if err := p.VerboseEqual(msg); err != nil { 1129 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1130 | } 1131 | if !p.Equal(msg) { 1132 | t.Fatalf("%#v !Json Equal %#v", msg, p) 1133 | } 1134 | } 1135 | func TestUserMessageProtoText(t *testing2.T) { 1136 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1137 | p := NewPopulatedUserMessage(popr, true) 1138 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1139 | msg := &UserMessage{} 1140 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1141 | panic(err) 1142 | } 1143 | if err := p.VerboseEqual(msg); err != nil { 1144 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1145 | } 1146 | if !p.Equal(msg) { 1147 | t.Fatalf("%#v !Proto %#v", msg, p) 1148 | } 1149 | } 1150 | 1151 | func TestUserMessageProtoCompactText(t *testing2.T) { 1152 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1153 | p := NewPopulatedUserMessage(popr, true) 1154 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1155 | msg := &UserMessage{} 1156 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1157 | panic(err) 1158 | } 1159 | if err := p.VerboseEqual(msg); err != nil { 1160 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1161 | } 1162 | if !p.Equal(msg) { 1163 | t.Fatalf("%#v !Proto %#v", msg, p) 1164 | } 1165 | } 1166 | 1167 | func TestJoinProtoText(t *testing2.T) { 1168 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1169 | p := NewPopulatedJoin(popr, true) 1170 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1171 | msg := &Join{} 1172 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1173 | panic(err) 1174 | } 1175 | if err := p.VerboseEqual(msg); err != nil { 1176 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1177 | } 1178 | if !p.Equal(msg) { 1179 | t.Fatalf("%#v !Proto %#v", msg, p) 1180 | } 1181 | } 1182 | 1183 | func TestJoinProtoCompactText(t *testing2.T) { 1184 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1185 | p := NewPopulatedJoin(popr, true) 1186 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1187 | msg := &Join{} 1188 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1189 | panic(err) 1190 | } 1191 | if err := p.VerboseEqual(msg); err != nil { 1192 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1193 | } 1194 | if !p.Equal(msg) { 1195 | t.Fatalf("%#v !Proto %#v", msg, p) 1196 | } 1197 | } 1198 | 1199 | func TestJoinReplyProtoText(t *testing2.T) { 1200 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1201 | p := NewPopulatedJoinReply(popr, true) 1202 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1203 | msg := &JoinReply{} 1204 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1205 | panic(err) 1206 | } 1207 | if err := p.VerboseEqual(msg); err != nil { 1208 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1209 | } 1210 | if !p.Equal(msg) { 1211 | t.Fatalf("%#v !Proto %#v", msg, p) 1212 | } 1213 | } 1214 | 1215 | func TestJoinReplyProtoCompactText(t *testing2.T) { 1216 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1217 | p := NewPopulatedJoinReply(popr, true) 1218 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1219 | msg := &JoinReply{} 1220 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1221 | panic(err) 1222 | } 1223 | if err := p.VerboseEqual(msg); err != nil { 1224 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1225 | } 1226 | if !p.Equal(msg) { 1227 | t.Fatalf("%#v !Proto %#v", msg, p) 1228 | } 1229 | } 1230 | 1231 | func TestNeighborProtoText(t *testing2.T) { 1232 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1233 | p := NewPopulatedNeighbor(popr, true) 1234 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1235 | msg := &Neighbor{} 1236 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1237 | panic(err) 1238 | } 1239 | if err := p.VerboseEqual(msg); err != nil { 1240 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1241 | } 1242 | if !p.Equal(msg) { 1243 | t.Fatalf("%#v !Proto %#v", msg, p) 1244 | } 1245 | } 1246 | 1247 | func TestNeighborProtoCompactText(t *testing2.T) { 1248 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1249 | p := NewPopulatedNeighbor(popr, true) 1250 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1251 | msg := &Neighbor{} 1252 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1253 | panic(err) 1254 | } 1255 | if err := p.VerboseEqual(msg); err != nil { 1256 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1257 | } 1258 | if !p.Equal(msg) { 1259 | t.Fatalf("%#v !Proto %#v", msg, p) 1260 | } 1261 | } 1262 | 1263 | func TestNeighborReplyProtoText(t *testing2.T) { 1264 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1265 | p := NewPopulatedNeighborReply(popr, true) 1266 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1267 | msg := &NeighborReply{} 1268 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1269 | panic(err) 1270 | } 1271 | if err := p.VerboseEqual(msg); err != nil { 1272 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1273 | } 1274 | if !p.Equal(msg) { 1275 | t.Fatalf("%#v !Proto %#v", msg, p) 1276 | } 1277 | } 1278 | 1279 | func TestNeighborReplyProtoCompactText(t *testing2.T) { 1280 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1281 | p := NewPopulatedNeighborReply(popr, true) 1282 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1283 | msg := &NeighborReply{} 1284 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1285 | panic(err) 1286 | } 1287 | if err := p.VerboseEqual(msg); err != nil { 1288 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1289 | } 1290 | if !p.Equal(msg) { 1291 | t.Fatalf("%#v !Proto %#v", msg, p) 1292 | } 1293 | } 1294 | 1295 | func TestForwardJoinProtoText(t *testing2.T) { 1296 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1297 | p := NewPopulatedForwardJoin(popr, true) 1298 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1299 | msg := &ForwardJoin{} 1300 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1301 | panic(err) 1302 | } 1303 | if err := p.VerboseEqual(msg); err != nil { 1304 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1305 | } 1306 | if !p.Equal(msg) { 1307 | t.Fatalf("%#v !Proto %#v", msg, p) 1308 | } 1309 | } 1310 | 1311 | func TestForwardJoinProtoCompactText(t *testing2.T) { 1312 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1313 | p := NewPopulatedForwardJoin(popr, true) 1314 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1315 | msg := &ForwardJoin{} 1316 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1317 | panic(err) 1318 | } 1319 | if err := p.VerboseEqual(msg); err != nil { 1320 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1321 | } 1322 | if !p.Equal(msg) { 1323 | t.Fatalf("%#v !Proto %#v", msg, p) 1324 | } 1325 | } 1326 | 1327 | func TestDisconnectProtoText(t *testing2.T) { 1328 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1329 | p := NewPopulatedDisconnect(popr, true) 1330 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1331 | msg := &Disconnect{} 1332 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1333 | panic(err) 1334 | } 1335 | if err := p.VerboseEqual(msg); err != nil { 1336 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1337 | } 1338 | if !p.Equal(msg) { 1339 | t.Fatalf("%#v !Proto %#v", msg, p) 1340 | } 1341 | } 1342 | 1343 | func TestDisconnectProtoCompactText(t *testing2.T) { 1344 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1345 | p := NewPopulatedDisconnect(popr, true) 1346 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1347 | msg := &Disconnect{} 1348 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1349 | panic(err) 1350 | } 1351 | if err := p.VerboseEqual(msg); err != nil { 1352 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1353 | } 1354 | if !p.Equal(msg) { 1355 | t.Fatalf("%#v !Proto %#v", msg, p) 1356 | } 1357 | } 1358 | 1359 | func TestCandidateProtoText(t *testing2.T) { 1360 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1361 | p := NewPopulatedCandidate(popr, true) 1362 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1363 | msg := &Candidate{} 1364 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1365 | panic(err) 1366 | } 1367 | if err := p.VerboseEqual(msg); err != nil { 1368 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1369 | } 1370 | if !p.Equal(msg) { 1371 | t.Fatalf("%#v !Proto %#v", msg, p) 1372 | } 1373 | } 1374 | 1375 | func TestCandidateProtoCompactText(t *testing2.T) { 1376 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1377 | p := NewPopulatedCandidate(popr, true) 1378 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1379 | msg := &Candidate{} 1380 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1381 | panic(err) 1382 | } 1383 | if err := p.VerboseEqual(msg); err != nil { 1384 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1385 | } 1386 | if !p.Equal(msg) { 1387 | t.Fatalf("%#v !Proto %#v", msg, p) 1388 | } 1389 | } 1390 | 1391 | func TestShuffleProtoText(t *testing2.T) { 1392 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1393 | p := NewPopulatedShuffle(popr, true) 1394 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1395 | msg := &Shuffle{} 1396 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1397 | panic(err) 1398 | } 1399 | if err := p.VerboseEqual(msg); err != nil { 1400 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1401 | } 1402 | if !p.Equal(msg) { 1403 | t.Fatalf("%#v !Proto %#v", msg, p) 1404 | } 1405 | } 1406 | 1407 | func TestShuffleProtoCompactText(t *testing2.T) { 1408 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1409 | p := NewPopulatedShuffle(popr, true) 1410 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1411 | msg := &Shuffle{} 1412 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1413 | panic(err) 1414 | } 1415 | if err := p.VerboseEqual(msg); err != nil { 1416 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1417 | } 1418 | if !p.Equal(msg) { 1419 | t.Fatalf("%#v !Proto %#v", msg, p) 1420 | } 1421 | } 1422 | 1423 | func TestShuffleReplyProtoText(t *testing2.T) { 1424 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1425 | p := NewPopulatedShuffleReply(popr, true) 1426 | data := code_google_com_p_gogoprotobuf_proto1.MarshalTextString(p) 1427 | msg := &ShuffleReply{} 1428 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1429 | panic(err) 1430 | } 1431 | if err := p.VerboseEqual(msg); err != nil { 1432 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1433 | } 1434 | if !p.Equal(msg) { 1435 | t.Fatalf("%#v !Proto %#v", msg, p) 1436 | } 1437 | } 1438 | 1439 | func TestShuffleReplyProtoCompactText(t *testing2.T) { 1440 | popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 1441 | p := NewPopulatedShuffleReply(popr, true) 1442 | data := code_google_com_p_gogoprotobuf_proto1.CompactTextString(p) 1443 | msg := &ShuffleReply{} 1444 | if err := code_google_com_p_gogoprotobuf_proto1.UnmarshalText(data, msg); err != nil { 1445 | panic(err) 1446 | } 1447 | if err := p.VerboseEqual(msg); err != nil { 1448 | t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 1449 | } 1450 | if !p.Equal(msg) { 1451 | t.Fatalf("%#v !Proto %#v", msg, p) 1452 | } 1453 | } 1454 | 1455 | func TestUserMessageStringer(t *testing3.T) { 1456 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1457 | p := NewPopulatedUserMessage(popr, false) 1458 | s1 := p.String() 1459 | s2 := fmt.Sprintf("%v", p) 1460 | if s1 != s2 { 1461 | t.Fatalf("String want %v got %v", s1, s2) 1462 | } 1463 | } 1464 | func TestJoinStringer(t *testing3.T) { 1465 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1466 | p := NewPopulatedJoin(popr, false) 1467 | s1 := p.String() 1468 | s2 := fmt.Sprintf("%v", p) 1469 | if s1 != s2 { 1470 | t.Fatalf("String want %v got %v", s1, s2) 1471 | } 1472 | } 1473 | func TestJoinReplyStringer(t *testing3.T) { 1474 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1475 | p := NewPopulatedJoinReply(popr, false) 1476 | s1 := p.String() 1477 | s2 := fmt.Sprintf("%v", p) 1478 | if s1 != s2 { 1479 | t.Fatalf("String want %v got %v", s1, s2) 1480 | } 1481 | } 1482 | func TestNeighborStringer(t *testing3.T) { 1483 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1484 | p := NewPopulatedNeighbor(popr, false) 1485 | s1 := p.String() 1486 | s2 := fmt.Sprintf("%v", p) 1487 | if s1 != s2 { 1488 | t.Fatalf("String want %v got %v", s1, s2) 1489 | } 1490 | } 1491 | func TestNeighborReplyStringer(t *testing3.T) { 1492 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1493 | p := NewPopulatedNeighborReply(popr, false) 1494 | s1 := p.String() 1495 | s2 := fmt.Sprintf("%v", p) 1496 | if s1 != s2 { 1497 | t.Fatalf("String want %v got %v", s1, s2) 1498 | } 1499 | } 1500 | func TestForwardJoinStringer(t *testing3.T) { 1501 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1502 | p := NewPopulatedForwardJoin(popr, false) 1503 | s1 := p.String() 1504 | s2 := fmt.Sprintf("%v", p) 1505 | if s1 != s2 { 1506 | t.Fatalf("String want %v got %v", s1, s2) 1507 | } 1508 | } 1509 | func TestDisconnectStringer(t *testing3.T) { 1510 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1511 | p := NewPopulatedDisconnect(popr, false) 1512 | s1 := p.String() 1513 | s2 := fmt.Sprintf("%v", p) 1514 | if s1 != s2 { 1515 | t.Fatalf("String want %v got %v", s1, s2) 1516 | } 1517 | } 1518 | func TestCandidateStringer(t *testing3.T) { 1519 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1520 | p := NewPopulatedCandidate(popr, false) 1521 | s1 := p.String() 1522 | s2 := fmt.Sprintf("%v", p) 1523 | if s1 != s2 { 1524 | t.Fatalf("String want %v got %v", s1, s2) 1525 | } 1526 | } 1527 | func TestShuffleStringer(t *testing3.T) { 1528 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1529 | p := NewPopulatedShuffle(popr, false) 1530 | s1 := p.String() 1531 | s2 := fmt.Sprintf("%v", p) 1532 | if s1 != s2 { 1533 | t.Fatalf("String want %v got %v", s1, s2) 1534 | } 1535 | } 1536 | func TestShuffleReplyStringer(t *testing3.T) { 1537 | popr := math_rand3.New(math_rand3.NewSource(time3.Now().UnixNano())) 1538 | p := NewPopulatedShuffleReply(popr, false) 1539 | s1 := p.String() 1540 | s2 := fmt.Sprintf("%v", p) 1541 | if s1 != s2 { 1542 | t.Fatalf("String want %v got %v", s1, s2) 1543 | } 1544 | } 1545 | func TestUserMessageSize(t *testing4.T) { 1546 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1547 | p := NewPopulatedUserMessage(popr, true) 1548 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1549 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1550 | if err != nil { 1551 | panic(err) 1552 | } 1553 | size := p.Size() 1554 | if len(data) != size { 1555 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1556 | } 1557 | if size2 != size { 1558 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1559 | } 1560 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1561 | if size3 != size { 1562 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1563 | } 1564 | } 1565 | 1566 | func BenchmarkUserMessageSize(b *testing4.B) { 1567 | popr := math_rand4.New(math_rand4.NewSource(616)) 1568 | total := 0 1569 | pops := make([]*UserMessage, 1000) 1570 | for i := 0; i < 1000; i++ { 1571 | pops[i] = NewPopulatedUserMessage(popr, false) 1572 | } 1573 | b.ResetTimer() 1574 | for i := 0; i < b.N; i++ { 1575 | total += pops[i%1000].Size() 1576 | } 1577 | b.SetBytes(int64(total / b.N)) 1578 | } 1579 | 1580 | func TestJoinSize(t *testing4.T) { 1581 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1582 | p := NewPopulatedJoin(popr, true) 1583 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1584 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1585 | if err != nil { 1586 | panic(err) 1587 | } 1588 | size := p.Size() 1589 | if len(data) != size { 1590 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1591 | } 1592 | if size2 != size { 1593 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1594 | } 1595 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1596 | if size3 != size { 1597 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1598 | } 1599 | } 1600 | 1601 | func BenchmarkJoinSize(b *testing4.B) { 1602 | popr := math_rand4.New(math_rand4.NewSource(616)) 1603 | total := 0 1604 | pops := make([]*Join, 1000) 1605 | for i := 0; i < 1000; i++ { 1606 | pops[i] = NewPopulatedJoin(popr, false) 1607 | } 1608 | b.ResetTimer() 1609 | for i := 0; i < b.N; i++ { 1610 | total += pops[i%1000].Size() 1611 | } 1612 | b.SetBytes(int64(total / b.N)) 1613 | } 1614 | 1615 | func TestJoinReplySize(t *testing4.T) { 1616 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1617 | p := NewPopulatedJoinReply(popr, true) 1618 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1619 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1620 | if err != nil { 1621 | panic(err) 1622 | } 1623 | size := p.Size() 1624 | if len(data) != size { 1625 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1626 | } 1627 | if size2 != size { 1628 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1629 | } 1630 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1631 | if size3 != size { 1632 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1633 | } 1634 | } 1635 | 1636 | func BenchmarkJoinReplySize(b *testing4.B) { 1637 | popr := math_rand4.New(math_rand4.NewSource(616)) 1638 | total := 0 1639 | pops := make([]*JoinReply, 1000) 1640 | for i := 0; i < 1000; i++ { 1641 | pops[i] = NewPopulatedJoinReply(popr, false) 1642 | } 1643 | b.ResetTimer() 1644 | for i := 0; i < b.N; i++ { 1645 | total += pops[i%1000].Size() 1646 | } 1647 | b.SetBytes(int64(total / b.N)) 1648 | } 1649 | 1650 | func TestNeighborSize(t *testing4.T) { 1651 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1652 | p := NewPopulatedNeighbor(popr, true) 1653 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1654 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1655 | if err != nil { 1656 | panic(err) 1657 | } 1658 | size := p.Size() 1659 | if len(data) != size { 1660 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1661 | } 1662 | if size2 != size { 1663 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1664 | } 1665 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1666 | if size3 != size { 1667 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1668 | } 1669 | } 1670 | 1671 | func BenchmarkNeighborSize(b *testing4.B) { 1672 | popr := math_rand4.New(math_rand4.NewSource(616)) 1673 | total := 0 1674 | pops := make([]*Neighbor, 1000) 1675 | for i := 0; i < 1000; i++ { 1676 | pops[i] = NewPopulatedNeighbor(popr, false) 1677 | } 1678 | b.ResetTimer() 1679 | for i := 0; i < b.N; i++ { 1680 | total += pops[i%1000].Size() 1681 | } 1682 | b.SetBytes(int64(total / b.N)) 1683 | } 1684 | 1685 | func TestNeighborReplySize(t *testing4.T) { 1686 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1687 | p := NewPopulatedNeighborReply(popr, true) 1688 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1689 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1690 | if err != nil { 1691 | panic(err) 1692 | } 1693 | size := p.Size() 1694 | if len(data) != size { 1695 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1696 | } 1697 | if size2 != size { 1698 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1699 | } 1700 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1701 | if size3 != size { 1702 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1703 | } 1704 | } 1705 | 1706 | func BenchmarkNeighborReplySize(b *testing4.B) { 1707 | popr := math_rand4.New(math_rand4.NewSource(616)) 1708 | total := 0 1709 | pops := make([]*NeighborReply, 1000) 1710 | for i := 0; i < 1000; i++ { 1711 | pops[i] = NewPopulatedNeighborReply(popr, false) 1712 | } 1713 | b.ResetTimer() 1714 | for i := 0; i < b.N; i++ { 1715 | total += pops[i%1000].Size() 1716 | } 1717 | b.SetBytes(int64(total / b.N)) 1718 | } 1719 | 1720 | func TestForwardJoinSize(t *testing4.T) { 1721 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1722 | p := NewPopulatedForwardJoin(popr, true) 1723 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1724 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1725 | if err != nil { 1726 | panic(err) 1727 | } 1728 | size := p.Size() 1729 | if len(data) != size { 1730 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1731 | } 1732 | if size2 != size { 1733 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1734 | } 1735 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1736 | if size3 != size { 1737 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1738 | } 1739 | } 1740 | 1741 | func BenchmarkForwardJoinSize(b *testing4.B) { 1742 | popr := math_rand4.New(math_rand4.NewSource(616)) 1743 | total := 0 1744 | pops := make([]*ForwardJoin, 1000) 1745 | for i := 0; i < 1000; i++ { 1746 | pops[i] = NewPopulatedForwardJoin(popr, false) 1747 | } 1748 | b.ResetTimer() 1749 | for i := 0; i < b.N; i++ { 1750 | total += pops[i%1000].Size() 1751 | } 1752 | b.SetBytes(int64(total / b.N)) 1753 | } 1754 | 1755 | func TestDisconnectSize(t *testing4.T) { 1756 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1757 | p := NewPopulatedDisconnect(popr, true) 1758 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1759 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1760 | if err != nil { 1761 | panic(err) 1762 | } 1763 | size := p.Size() 1764 | if len(data) != size { 1765 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1766 | } 1767 | if size2 != size { 1768 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1769 | } 1770 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1771 | if size3 != size { 1772 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1773 | } 1774 | } 1775 | 1776 | func BenchmarkDisconnectSize(b *testing4.B) { 1777 | popr := math_rand4.New(math_rand4.NewSource(616)) 1778 | total := 0 1779 | pops := make([]*Disconnect, 1000) 1780 | for i := 0; i < 1000; i++ { 1781 | pops[i] = NewPopulatedDisconnect(popr, false) 1782 | } 1783 | b.ResetTimer() 1784 | for i := 0; i < b.N; i++ { 1785 | total += pops[i%1000].Size() 1786 | } 1787 | b.SetBytes(int64(total / b.N)) 1788 | } 1789 | 1790 | func TestCandidateSize(t *testing4.T) { 1791 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1792 | p := NewPopulatedCandidate(popr, true) 1793 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1794 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1795 | if err != nil { 1796 | panic(err) 1797 | } 1798 | size := p.Size() 1799 | if len(data) != size { 1800 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1801 | } 1802 | if size2 != size { 1803 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1804 | } 1805 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1806 | if size3 != size { 1807 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1808 | } 1809 | } 1810 | 1811 | func BenchmarkCandidateSize(b *testing4.B) { 1812 | popr := math_rand4.New(math_rand4.NewSource(616)) 1813 | total := 0 1814 | pops := make([]*Candidate, 1000) 1815 | for i := 0; i < 1000; i++ { 1816 | pops[i] = NewPopulatedCandidate(popr, false) 1817 | } 1818 | b.ResetTimer() 1819 | for i := 0; i < b.N; i++ { 1820 | total += pops[i%1000].Size() 1821 | } 1822 | b.SetBytes(int64(total / b.N)) 1823 | } 1824 | 1825 | func TestShuffleSize(t *testing4.T) { 1826 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1827 | p := NewPopulatedShuffle(popr, true) 1828 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1829 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1830 | if err != nil { 1831 | panic(err) 1832 | } 1833 | size := p.Size() 1834 | if len(data) != size { 1835 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1836 | } 1837 | if size2 != size { 1838 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1839 | } 1840 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1841 | if size3 != size { 1842 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1843 | } 1844 | } 1845 | 1846 | func BenchmarkShuffleSize(b *testing4.B) { 1847 | popr := math_rand4.New(math_rand4.NewSource(616)) 1848 | total := 0 1849 | pops := make([]*Shuffle, 1000) 1850 | for i := 0; i < 1000; i++ { 1851 | pops[i] = NewPopulatedShuffle(popr, false) 1852 | } 1853 | b.ResetTimer() 1854 | for i := 0; i < b.N; i++ { 1855 | total += pops[i%1000].Size() 1856 | } 1857 | b.SetBytes(int64(total / b.N)) 1858 | } 1859 | 1860 | func TestShuffleReplySize(t *testing4.T) { 1861 | popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano())) 1862 | p := NewPopulatedShuffleReply(popr, true) 1863 | size2 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1864 | data, err := code_google_com_p_gogoprotobuf_proto2.Marshal(p) 1865 | if err != nil { 1866 | panic(err) 1867 | } 1868 | size := p.Size() 1869 | if len(data) != size { 1870 | t.Fatalf("size %v != marshalled size %v", size, len(data)) 1871 | } 1872 | if size2 != size { 1873 | t.Fatalf("size %v != before marshal proto.Size %v", size, size2) 1874 | } 1875 | size3 := code_google_com_p_gogoprotobuf_proto2.Size(p) 1876 | if size3 != size { 1877 | t.Fatalf("size %v != after marshal proto.Size %v", size, size3) 1878 | } 1879 | } 1880 | 1881 | func BenchmarkShuffleReplySize(b *testing4.B) { 1882 | popr := math_rand4.New(math_rand4.NewSource(616)) 1883 | total := 0 1884 | pops := make([]*ShuffleReply, 1000) 1885 | for i := 0; i < 1000; i++ { 1886 | pops[i] = NewPopulatedShuffleReply(popr, false) 1887 | } 1888 | b.ResetTimer() 1889 | for i := 0; i < b.N; i++ { 1890 | total += pops[i%1000].Size() 1891 | } 1892 | b.SetBytes(int64(total / b.N)) 1893 | } 1894 | 1895 | func TestUserMessageGoString(t *testing5.T) { 1896 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 1897 | p := NewPopulatedUserMessage(popr, false) 1898 | s1 := p.GoString() 1899 | s2 := fmt1.Sprintf("%#v", p) 1900 | if s1 != s2 { 1901 | t.Fatalf("GoString want %v got %v", s1, s2) 1902 | } 1903 | _, err := go_parser.ParseExpr(s1) 1904 | if err != nil { 1905 | panic(err) 1906 | } 1907 | } 1908 | func TestJoinGoString(t *testing5.T) { 1909 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 1910 | p := NewPopulatedJoin(popr, false) 1911 | s1 := p.GoString() 1912 | s2 := fmt1.Sprintf("%#v", p) 1913 | if s1 != s2 { 1914 | t.Fatalf("GoString want %v got %v", s1, s2) 1915 | } 1916 | _, err := go_parser.ParseExpr(s1) 1917 | if err != nil { 1918 | panic(err) 1919 | } 1920 | } 1921 | func TestJoinReplyGoString(t *testing5.T) { 1922 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 1923 | p := NewPopulatedJoinReply(popr, false) 1924 | s1 := p.GoString() 1925 | s2 := fmt1.Sprintf("%#v", p) 1926 | if s1 != s2 { 1927 | t.Fatalf("GoString want %v got %v", s1, s2) 1928 | } 1929 | _, err := go_parser.ParseExpr(s1) 1930 | if err != nil { 1931 | panic(err) 1932 | } 1933 | } 1934 | func TestNeighborGoString(t *testing5.T) { 1935 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 1936 | p := NewPopulatedNeighbor(popr, false) 1937 | s1 := p.GoString() 1938 | s2 := fmt1.Sprintf("%#v", p) 1939 | if s1 != s2 { 1940 | t.Fatalf("GoString want %v got %v", s1, s2) 1941 | } 1942 | _, err := go_parser.ParseExpr(s1) 1943 | if err != nil { 1944 | panic(err) 1945 | } 1946 | } 1947 | func TestNeighborReplyGoString(t *testing5.T) { 1948 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 1949 | p := NewPopulatedNeighborReply(popr, false) 1950 | s1 := p.GoString() 1951 | s2 := fmt1.Sprintf("%#v", p) 1952 | if s1 != s2 { 1953 | t.Fatalf("GoString want %v got %v", s1, s2) 1954 | } 1955 | _, err := go_parser.ParseExpr(s1) 1956 | if err != nil { 1957 | panic(err) 1958 | } 1959 | } 1960 | func TestForwardJoinGoString(t *testing5.T) { 1961 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 1962 | p := NewPopulatedForwardJoin(popr, false) 1963 | s1 := p.GoString() 1964 | s2 := fmt1.Sprintf("%#v", p) 1965 | if s1 != s2 { 1966 | t.Fatalf("GoString want %v got %v", s1, s2) 1967 | } 1968 | _, err := go_parser.ParseExpr(s1) 1969 | if err != nil { 1970 | panic(err) 1971 | } 1972 | } 1973 | func TestDisconnectGoString(t *testing5.T) { 1974 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 1975 | p := NewPopulatedDisconnect(popr, false) 1976 | s1 := p.GoString() 1977 | s2 := fmt1.Sprintf("%#v", p) 1978 | if s1 != s2 { 1979 | t.Fatalf("GoString want %v got %v", s1, s2) 1980 | } 1981 | _, err := go_parser.ParseExpr(s1) 1982 | if err != nil { 1983 | panic(err) 1984 | } 1985 | } 1986 | func TestCandidateGoString(t *testing5.T) { 1987 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 1988 | p := NewPopulatedCandidate(popr, false) 1989 | s1 := p.GoString() 1990 | s2 := fmt1.Sprintf("%#v", p) 1991 | if s1 != s2 { 1992 | t.Fatalf("GoString want %v got %v", s1, s2) 1993 | } 1994 | _, err := go_parser.ParseExpr(s1) 1995 | if err != nil { 1996 | panic(err) 1997 | } 1998 | } 1999 | func TestShuffleGoString(t *testing5.T) { 2000 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 2001 | p := NewPopulatedShuffle(popr, false) 2002 | s1 := p.GoString() 2003 | s2 := fmt1.Sprintf("%#v", p) 2004 | if s1 != s2 { 2005 | t.Fatalf("GoString want %v got %v", s1, s2) 2006 | } 2007 | _, err := go_parser.ParseExpr(s1) 2008 | if err != nil { 2009 | panic(err) 2010 | } 2011 | } 2012 | func TestShuffleReplyGoString(t *testing5.T) { 2013 | popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano())) 2014 | p := NewPopulatedShuffleReply(popr, false) 2015 | s1 := p.GoString() 2016 | s2 := fmt1.Sprintf("%#v", p) 2017 | if s1 != s2 { 2018 | t.Fatalf("GoString want %v got %v", s1, s2) 2019 | } 2020 | _, err := go_parser.ParseExpr(s1) 2021 | if err != nil { 2022 | panic(err) 2023 | } 2024 | } 2025 | func TestUserMessageVerboseEqual(t *testing6.T) { 2026 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2027 | p := NewPopulatedUserMessage(popr, false) 2028 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2029 | if err != nil { 2030 | panic(err) 2031 | } 2032 | msg := &UserMessage{} 2033 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2034 | panic(err) 2035 | } 2036 | if err := p.VerboseEqual(msg); err != nil { 2037 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2038 | } 2039 | } 2040 | func TestJoinVerboseEqual(t *testing6.T) { 2041 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2042 | p := NewPopulatedJoin(popr, false) 2043 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2044 | if err != nil { 2045 | panic(err) 2046 | } 2047 | msg := &Join{} 2048 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2049 | panic(err) 2050 | } 2051 | if err := p.VerboseEqual(msg); err != nil { 2052 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2053 | } 2054 | } 2055 | func TestJoinReplyVerboseEqual(t *testing6.T) { 2056 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2057 | p := NewPopulatedJoinReply(popr, false) 2058 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2059 | if err != nil { 2060 | panic(err) 2061 | } 2062 | msg := &JoinReply{} 2063 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2064 | panic(err) 2065 | } 2066 | if err := p.VerboseEqual(msg); err != nil { 2067 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2068 | } 2069 | } 2070 | func TestNeighborVerboseEqual(t *testing6.T) { 2071 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2072 | p := NewPopulatedNeighbor(popr, false) 2073 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2074 | if err != nil { 2075 | panic(err) 2076 | } 2077 | msg := &Neighbor{} 2078 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2079 | panic(err) 2080 | } 2081 | if err := p.VerboseEqual(msg); err != nil { 2082 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2083 | } 2084 | } 2085 | func TestNeighborReplyVerboseEqual(t *testing6.T) { 2086 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2087 | p := NewPopulatedNeighborReply(popr, false) 2088 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2089 | if err != nil { 2090 | panic(err) 2091 | } 2092 | msg := &NeighborReply{} 2093 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2094 | panic(err) 2095 | } 2096 | if err := p.VerboseEqual(msg); err != nil { 2097 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2098 | } 2099 | } 2100 | func TestForwardJoinVerboseEqual(t *testing6.T) { 2101 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2102 | p := NewPopulatedForwardJoin(popr, false) 2103 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2104 | if err != nil { 2105 | panic(err) 2106 | } 2107 | msg := &ForwardJoin{} 2108 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2109 | panic(err) 2110 | } 2111 | if err := p.VerboseEqual(msg); err != nil { 2112 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2113 | } 2114 | } 2115 | func TestDisconnectVerboseEqual(t *testing6.T) { 2116 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2117 | p := NewPopulatedDisconnect(popr, false) 2118 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2119 | if err != nil { 2120 | panic(err) 2121 | } 2122 | msg := &Disconnect{} 2123 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2124 | panic(err) 2125 | } 2126 | if err := p.VerboseEqual(msg); err != nil { 2127 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2128 | } 2129 | } 2130 | func TestCandidateVerboseEqual(t *testing6.T) { 2131 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2132 | p := NewPopulatedCandidate(popr, false) 2133 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2134 | if err != nil { 2135 | panic(err) 2136 | } 2137 | msg := &Candidate{} 2138 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2139 | panic(err) 2140 | } 2141 | if err := p.VerboseEqual(msg); err != nil { 2142 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2143 | } 2144 | } 2145 | func TestShuffleVerboseEqual(t *testing6.T) { 2146 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2147 | p := NewPopulatedShuffle(popr, false) 2148 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2149 | if err != nil { 2150 | panic(err) 2151 | } 2152 | msg := &Shuffle{} 2153 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2154 | panic(err) 2155 | } 2156 | if err := p.VerboseEqual(msg); err != nil { 2157 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2158 | } 2159 | } 2160 | func TestShuffleReplyVerboseEqual(t *testing6.T) { 2161 | popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano())) 2162 | p := NewPopulatedShuffleReply(popr, false) 2163 | data, err := code_google_com_p_gogoprotobuf_proto3.Marshal(p) 2164 | if err != nil { 2165 | panic(err) 2166 | } 2167 | msg := &ShuffleReply{} 2168 | if err := code_google_com_p_gogoprotobuf_proto3.Unmarshal(data, msg); err != nil { 2169 | panic(err) 2170 | } 2171 | if err := p.VerboseEqual(msg); err != nil { 2172 | t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err) 2173 | } 2174 | } 2175 | 2176 | //These tests are generated by code.google.com/p/gogoprotobuf/plugin/testgen 2177 | -------------------------------------------------------------------------------- /node/node.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | // Node decribes a node in the overlay. 8 | type Node struct { 9 | // Id is the node's identification. 10 | Id uint64 `json:"id"` 11 | // Addr is the network address of the node, 12 | // in the form of "host:port". 13 | Addr string `json:"address"` 14 | // Conn is the (TCP) connection to the node. 15 | // If the node is in the passive view, then the Conn could be 16 | // nil. 17 | Conn *net.TCPConn `json:"-"` 18 | } 19 | -------------------------------------------------------------------------------- /rest/server.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | "os" 10 | "os/exec" 11 | 12 | "github.com/go-distributed/gog/agent" 13 | "github.com/go-distributed/gog/config" 14 | log "github.com/go-distributed/gog/log" 15 | ) 16 | 17 | const ( 18 | listURL = "/api/list" 19 | joinURL = "/api/join" 20 | broadcastURL = "/api/broadcast" 21 | configURL = "/api/config" 22 | leaveURL = "/api/leave" 23 | ) 24 | 25 | var ( 26 | errInvalidMethod = errors.New("server: Invalid method") 27 | ) 28 | 29 | // RESTServer handles RESTful requests for gog agent. 30 | type RESTServer struct { 31 | cfg *config.Config 32 | ag agent.Agent 33 | mux *http.ServeMux 34 | } 35 | 36 | // NewServer creates a new RESTful server for gog agent. 37 | // It will also starts the agent server. 38 | func NewServer(cfg *config.Config) *http.Server { 39 | handler := NewRESTServer(cfg) 40 | return &http.Server{ 41 | Addr: cfg.RESTAddrStr, 42 | Handler: handler, 43 | } 44 | } 45 | 46 | // NewRESTServer creates an http.Handler to handle HTTP requests. 47 | func NewRESTServer(cfg *config.Config) http.Handler { 48 | mux := http.NewServeMux() 49 | ag := agent.NewAgent(cfg) 50 | rh := &RESTServer{cfg, ag, mux} 51 | rh.RegisterAPI(mux) 52 | 53 | // Register a user message handler. 54 | ag.RegisterMessageHandler(rh.UserMessagHandler) 55 | 56 | // Start the agent server. 57 | go func() { 58 | if err := ag.Serve(); err != nil { 59 | log.Fatalf("server.NewServer(): Agent failed to serve: %v\n", err) 60 | } 61 | }() 62 | return rh 63 | } 64 | 65 | // registerAPI registers the api urls. 66 | func (rh *RESTServer) RegisterAPI(mux *http.ServeMux) { 67 | mux.HandleFunc(listURL, rh.List) 68 | mux.HandleFunc(joinURL, rh.Join) 69 | mux.HandleFunc(broadcastURL, rh.Broadcast) 70 | mux.HandleFunc(configURL, rh.Config) 71 | mux.HandleFunc(leaveURL, rh.Leave) 72 | return 73 | } 74 | 75 | // List lists the views. 76 | func (rh *RESTServer) List(w http.ResponseWriter, r *http.Request) { 77 | b, err := rh.ag.List() 78 | if err != nil { 79 | http.Error(w, err.Error(), http.StatusInternalServerError) 80 | return 81 | } 82 | fmt.Fprintf(w, string(b)) 83 | return 84 | } 85 | 86 | // Join joins the agent to a cluster. 87 | func (rh *RESTServer) Join(w http.ResponseWriter, r *http.Request) { 88 | var peers []string 89 | 90 | if r.Method != "POST" { 91 | http.Error(w, errInvalidMethod.Error(), http.StatusMethodNotAllowed) 92 | return 93 | } 94 | if err := r.ParseForm(); err != nil { 95 | http.Error(w, err.Error(), http.StatusBadRequest) 96 | return 97 | } 98 | 99 | peer := r.Form.Get("peer") 100 | 101 | // Join a single peer. 102 | if peer != "" { 103 | if err := rh.ag.Join(peer); err != nil { 104 | http.Error(w, err.Error(), http.StatusInternalServerError) 105 | return 106 | } 107 | return 108 | } 109 | 110 | // Join a cluster. 111 | b, err := ioutil.ReadAll(r.Body) 112 | if err != nil { 113 | http.Error(w, err.Error(), http.StatusBadRequest) 114 | return 115 | } 116 | if err := json.Unmarshal(b, &peers); err != nil { 117 | http.Error(w, err.Error(), http.StatusBadRequest) 118 | return 119 | } 120 | if err := rh.ag.Join(peers...); err != nil { 121 | http.Error(w, err.Error(), http.StatusInternalServerError) 122 | return 123 | } 124 | return 125 | } 126 | 127 | // Broadcast broadcasts the message to the cluster 128 | func (rh *RESTServer) Broadcast(w http.ResponseWriter, r *http.Request) { 129 | if err := r.ParseForm(); err != nil { 130 | http.Error(w, err.Error(), http.StatusBadRequest) 131 | return 132 | } 133 | 134 | msg := r.Form.Get("message") 135 | if msg != "" { 136 | log.Infof("Broadcasting: %s\n", msg) 137 | if err := rh.ag.Broadcast([]byte(msg)); err != nil { 138 | http.Error(w, err.Error(), http.StatusInternalServerError) 139 | return 140 | } 141 | } 142 | return 143 | } 144 | 145 | // Config get/set the current configuration. 146 | func (rh *RESTServer) Config(w http.ResponseWriter, r *http.Request) { 147 | b, err := json.Marshal(rh.cfg) 148 | if err != nil { 149 | http.Error(w, err.Error(), http.StatusInternalServerError) 150 | return 151 | } 152 | fmt.Fprint(w, string(b)) 153 | } 154 | 155 | // Leave makes the agent to exit. 156 | func (rh *RESTServer) Leave(w http.ResponseWriter, r *http.Request) { 157 | rh.ag.Leave() 158 | } 159 | 160 | // UserMessagHandler is the handler for user messages. It will run a script 161 | // specified by the configuration. 162 | func (rh *RESTServer) UserMessagHandler(msg []byte) { 163 | if rh.cfg.UserMsgHandler == "" { 164 | return 165 | } 166 | cmd := exec.Command(rh.cfg.UserMsgHandler, string(msg)) 167 | cmd.Stdout = os.Stdout 168 | cmd.Stderr = os.Stderr 169 | if err := cmd.Run(); err != nil { 170 | log.Errorf("server.UserMessageHandler(): Failed to run command: %v\n", err) 171 | } 172 | } 173 | 174 | // ServeHTTP implements the http.Handler for RESTServer. 175 | // It will get the handler from mux and invoke the handler. 176 | func (rh *RESTServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { 177 | h, _ := rh.mux.Handler(r) 178 | h.ServeHTTP(w, r) 179 | } 180 | -------------------------------------------------------------------------------- /test/genlist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Generate peer list. 4 | # usage: ./genlist.py [filename] [number_of_hosts] 5 | 6 | import sys 7 | import json 8 | 9 | startport = 8000 10 | 11 | def main(): 12 | if len(sys.argv) != 3: 13 | print "usage:", sys.argv[0], "[filename] [number_of_hosts]" 14 | return 15 | 16 | filename = sys.argv[1] 17 | n = int(sys.argv[2]) 18 | f = open(filename, "w+") 19 | 20 | peers = [] 21 | for i in range (0, int(n)): 22 | peer = "localhost:%d" % (startport+i) 23 | peers.append(peer) 24 | 25 | f.write(json.dumps(peers)) 26 | f.close() 27 | 28 | if __name__ == "__main__": 29 | main() 30 | -------------------------------------------------------------------------------- /test/process_log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import glob 4 | import sys 5 | 6 | logdir = "./log" 7 | 8 | def main(): 9 | if len(sys.argv) != 2: 10 | print "usage:", sys.argv[0], "[log_dir]" 11 | return 12 | 13 | global logdir 14 | 15 | logdir = sys.argv[1] 16 | stdoutdir = logdir + "/stdout" 17 | stderrdir = logdir + "/stderr" 18 | 19 | files = glob.glob(stdoutdir + "/*") 20 | 21 | print "hello" 22 | 23 | # print those isolated nodes. 24 | for name in files: 25 | f = open(name) 26 | line = f.read() 27 | f.close() 28 | if not "hello" in line: 29 | print name 30 | 31 | print "world" 32 | 33 | for name in files: 34 | f = open(name) 35 | line = f.read() 36 | f.close() 37 | if not "hello" in line: 38 | print name 39 | 40 | if __name__ == "__main__": 41 | main() 42 | -------------------------------------------------------------------------------- /test/query_handler.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl http://104.236.17.148:11000/received?color=$1 3 | -------------------------------------------------------------------------------- /test/run_cluster.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # start a gossip cluster. 4 | # usage: ./run_cluster.py [number_of_hosts] 5 | 6 | import os 7 | import subprocess 8 | import sys 9 | import time 10 | import random 11 | 12 | timer_addr = "localhost:11000" 13 | startport = 8000 14 | n = 10 15 | gogpath = "../gog" 16 | peerfile = "peers.json" 17 | genlist = "./genlist.py" 18 | logdir = "./log" 19 | userscript = "./query_handler.sh" 20 | 21 | process = [] 22 | addrs = [] 23 | rest_addrs = [] 24 | 25 | def startNode(addr, rest_addr): 26 | stdoutdir = logdir + "/stdout" 27 | stderrdir = logdir + "/stderr" 28 | 29 | if not os.path.exists(stdoutdir): 30 | os.makedirs(stdoutdir) 31 | if not os.path.exists(stderrdir): 32 | os.makedirs(stderrdir) 33 | 34 | stdoutpath = stdoutdir + "/" + addr 35 | stderrpath = stderrdir + "/" + addr 36 | 37 | stdoutf = open(stdoutpath, "w+") 38 | stderrf = open(stderrpath, "w+") 39 | 40 | p = subprocess.Popen([gogpath, "-addr", addr, "-rest-addr", rest_addr, "-user-message-handler", userscript, "-peer-file", peerfile], 41 | stdin=subprocess.PIPE, stdout=stdoutf, stderr=stderrf) 42 | process.append(p) 43 | 44 | def startNodes(): 45 | print "Launching %d nodes..." %n 46 | 47 | for i in range(0, n): 48 | addr = "localhost:%d" % (startport+i) 49 | rest_addr = "localhost:%d" % (startport+i+n) 50 | 51 | global addrs 52 | global rest_addrs 53 | 54 | addrs.append(addr) 55 | rest_addrs.append(rest_addr) 56 | 57 | print "Launching node %d..." %i 58 | startNode(addr, rest_addr) 59 | 60 | print "All nodes launched.\n" 61 | 62 | def joinNodes(): 63 | print "Joining %d nodes..." %n 64 | 65 | for i in range(0, len(rest_addrs)): 66 | rest_addr = rest_addrs[i] 67 | #subprocess.call(["curl", "-d", "@"+peerfile, "-H", "Content-Type: application/json", "http://"+rest_addr+"/api/join"]) 68 | subprocess.call(["curl", "http://"+rest_addr+"/api/join", "-d", "peer=localhost:8000"]) 69 | 70 | def listViews(): 71 | nullf = open("/dev/null", "w") 72 | for i in range(0, len(rest_addrs)): 73 | rest_addr = rest_addrs[i] 74 | subprocess.call(["curl", "http://"+rest_addr+"/api/list"], stdout=nullf, stderr=nullf) 75 | 76 | def main(): 77 | if len(sys.argv) != 4: 78 | print "usage:", sys.argv[0], "[gogpath]", "[number_of_hosts]", "[number_of_kill]" 79 | return 80 | 81 | global gopath 82 | global n 83 | 84 | gogpath = sys.argv[1] 85 | n = int(sys.argv[2]) 86 | m = int(sys.argv[3]) 87 | 88 | subprocess.call([genlist, peerfile, str(n)]) 89 | 90 | # run nodes 91 | startNodes() 92 | 93 | time.sleep(1) 94 | 95 | # connecting nodes 96 | joinNodes() 97 | 98 | for i in range(0, 5): 99 | print "Listing views %d..." %i 100 | time.sleep(1) 101 | listViews() 102 | 103 | print "Broadcasting message" 104 | # start timer 105 | subprocess.call(["curl", "http://"+timer_addr+"/start"]) 106 | 107 | # send message 108 | subprocess.call(["curl", "http://"+rest_addrs[0]+"/api/broadcast", "-d", "message=hello"]) 109 | 110 | while True: 111 | continue 112 | 113 | #print "listing..." 114 | #i = 0 115 | #for p in process: 116 | # print "list %d" %i 117 | # i = i + 1 118 | # p.stdin.write("list\n") 119 | # 120 | #time.sleep(1) 121 | #print "sending..." 122 | #process[0].stdin.write("hello\n") 123 | # 124 | #time.sleep(5) 125 | # 126 | #print "randomly killing %d nodes..." %m 127 | #for i in range (0, m): 128 | # index = random.randint(0, n-1) 129 | # p = process[index] 130 | # while p is None: 131 | # index = (index + 1) % n 132 | # p = process[index] 133 | # process[index].kill() 134 | # process[index] = None 135 | # 136 | #time.sleep(5) 137 | #i = 0 138 | #for p in process: 139 | # if not p is None: 140 | # print "list %d" %i 141 | # p.stdin.write("list\n") 142 | # i = i + 1 143 | # 144 | #for p in process: 145 | # if not p is None: 146 | # print "sending..." 147 | # p.stdin.write("world\n") 148 | # break 149 | # 150 | #time.sleep(10) 151 | 152 | if __name__ == "__main__": 153 | main() 154 | -------------------------------------------------------------------------------- /test/run_serfcluster.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # start a gossip cluster. 4 | # usage: ./run_cluster.py [number_of_hosts] 5 | 6 | import os 7 | import subprocess 8 | import sys 9 | import time 10 | 11 | n = 10 12 | filename = "peerlist.txt" 13 | genlist = "./genlist.py" 14 | logdir = "./log" 15 | 16 | process = [] 17 | 18 | def joinNodes(): 19 | print "Joining %d nodes..." %n 20 | 21 | f = open(filename) 22 | lines = f.readlines() 23 | f.close() 24 | 25 | i = 0 26 | 27 | first_rpcaddr = lines[1][:-1] 28 | while i < len(lines): 29 | print "Joining node %d..." %(i/2) 30 | hostport = lines[i][:-1] 31 | subprocess.call(["serf", "join", "-rpc-addr", first_rpcaddr, hostport], stdout=None) 32 | i = i + 2 33 | 34 | print "All nodes joined.\n" 35 | 36 | 37 | def startNode(hostport, rpcaddr): 38 | stdoutdir = logdir + "/stdout" 39 | stderrdir = logdir + "/stderr" 40 | 41 | if not os.path.exists(stdoutdir): 42 | os.makedirs(stdoutdir) 43 | if not os.path.exists(stderrdir): 44 | os.makedirs(stderrdir) 45 | 46 | stdoutpath = stdoutdir + "/" + hostport 47 | stderrpath = stderrdir + "/" + hostport 48 | 49 | stdoutf = open(stdoutpath, "w+") 50 | stderrf = open(stderrpath, "w+") 51 | 52 | p = subprocess.Popen(["serf", "agent", "-node", hostport, "-bind", hostport, "-rpc-addr", rpcaddr], 53 | stdin=subprocess.PIPE, stdout=stdoutf, stderr=stderrf) 54 | process.append(p) 55 | 56 | 57 | def startNodes(): 58 | print "Launching %d nodes..." %n 59 | f = open(filename) 60 | lines = f.readlines() 61 | f.close() 62 | 63 | i = 0 64 | while i < len(lines): 65 | print "Launching node %d..." %(i/2) 66 | startNode(lines[i][:-1], lines[i+1][:-1]) 67 | i = i + 2 68 | 69 | print "All nodes launched.\n" 70 | 71 | def generateList(n): 72 | print "Generating peer list file..." 73 | subprocess.call([genlist, filename, str(2*n)]) 74 | print "Ok.\n" 75 | 76 | def main(): 77 | if len(sys.argv) != 3: 78 | print "usage:", sys.argv[0], "[number_of_hosts]", "[log_dir]" 79 | return 80 | 81 | global gopath 82 | global n 83 | global logdir 84 | 85 | n = int(sys.argv[1]) 86 | logdir = sys.argv[2] 87 | 88 | # generate host list 89 | generateList(n) 90 | 91 | # run node 92 | startNodes() 93 | 94 | time.sleep(1) 95 | 96 | joinNodes() 97 | 98 | # list member 99 | subprocess.call(["serf", "members", "-rpc-addr", "localhost:8001"]) 100 | 101 | # send a message 102 | subprocess.call(["serf", "event", "-rpc-addr", "localhost:8001", "hello", "hello"]) 103 | 104 | while True: 105 | continue 106 | 107 | if __name__ == "__main__": 108 | main() 109 | -------------------------------------------------------------------------------- /test/rungog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ $# != 1 ]]; then 4 | echo "usage: $0 [number_of_agents]" 5 | exit -1 6 | fi 7 | 8 | num=$1 9 | gopath=/root/gopher 10 | interface=eth0 11 | 12 | ipaddr=$(ifconfig $interface | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}') 13 | echo $ipaddr 14 | 15 | rootpath=$gopath/src/github.com/go-distributed/gog 16 | logpath=$rootpath/test/log 17 | 18 | userscript=$rootpath/test/query_handler.sh 19 | 20 | for i in `seq 1 $num`; 21 | do 22 | let agentport=8000+$i-1 23 | let restport=9000+$i-1 24 | 25 | agentaddr=$ipaddr:$agentport 26 | restaddr=$ipaddr:$restport 27 | 28 | mkdir $logpath/$agentaddr 29 | 30 | $rootpath/gog -addr=$agentaddr -rest-addr=$restaddr -user-message-handler=$userscript > $logpath/$agentaddr/stdout 2>$logpath/$agentaddr/stderr & 31 | done 32 | -------------------------------------------------------------------------------- /test/timer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io/ioutil" 7 | "math" 8 | "net/http" 9 | "strconv" 10 | "strings" 11 | "sync" 12 | "sync/atomic" 13 | "time" 14 | ) 15 | 16 | var hostport string 17 | 18 | var receivedNum int32 19 | var startTime time.Time 20 | var elaspedTime time.Duration 21 | 22 | var vmu sync.Mutex 23 | var aViewCnt = make(map[string]int) 24 | var pViewCnt = make(map[string]int) 25 | var times = make([]time.Duration, 21) 26 | 27 | var testSerf bool 28 | 29 | func handleStart(w http.ResponseWriter, r *http.Request) { 30 | startTime = time.Now() 31 | elaspedTime = 0 32 | receivedNum = 0 33 | times = make([]time.Duration, 21) 34 | aViewCnt = make(map[string]int) 35 | pViewCnt = make(map[string]int) 36 | } 37 | 38 | func handleReceived(w http.ResponseWriter, r *http.Request) { 39 | reqstart := time.Now() 40 | num := atomic.AddInt32(&receivedNum, 1) 41 | if num == 1 { 42 | startTime = time.Now() 43 | } 44 | elaspedTime = time.Now().Sub(startTime) 45 | if !testSerf { 46 | if num%100 == 0 { 47 | times[num/100] = elaspedTime 48 | } 49 | } else { 50 | if num%20 == 0 { 51 | times[num/20] = elaspedTime 52 | } 53 | } 54 | b, err := ioutil.ReadAll(r.Body) 55 | if err != nil { 56 | fmt.Println(err) 57 | return 58 | } 59 | fmt.Println(string(b)) 60 | fmt.Fprintf(w, "hello %d, time: %v, req time: %v", num, elaspedTime, time.Now().Sub(reqstart)) 61 | } 62 | 63 | func handleQuery(w http.ResponseWriter, r *http.Request) { 64 | if !testSerf { 65 | for i := range times { 66 | fmt.Fprintf(w, "Received: %d, time: %v\n", i*100, times[i]) 67 | } 68 | } else { 69 | for i := range times { 70 | fmt.Fprintf(w, "Received: %d, time: %v\n", i*20, times[i]) 71 | } 72 | } 73 | fmt.Fprintf(w, "total received: %d, elasped time: %v\n", receivedNum, elaspedTime) 74 | 75 | vmu.Lock() 76 | defer vmu.Unlock() 77 | 78 | avg, std := computeView(aViewCnt) 79 | fmt.Fprintf(w, "Aview avg: %v, std: %v\n", avg, std) 80 | avg, std = computeView(pViewCnt) 81 | fmt.Fprintf(w, "Pview avg: %v, std: %v\n", avg, std) 82 | } 83 | 84 | func handleView(w http.ResponseWriter, r *http.Request) { 85 | b, err := ioutil.ReadAll(r.Body) 86 | if err != nil { 87 | fmt.Println(err) 88 | return 89 | } 90 | 91 | // "aviewCnt:pviewCnt:id" 92 | view := strings.SplitAfterN(string(b), ":", 3) 93 | 94 | av, err := strconv.Atoi(view[0][:len(view[0])-1]) 95 | if err != nil { 96 | fmt.Println(err) 97 | return 98 | } 99 | pv, err := strconv.Atoi(view[1][:len(view[1])-1]) 100 | if err != nil { 101 | fmt.Println(err) 102 | return 103 | } 104 | 105 | vmu.Lock() 106 | defer vmu.Unlock() 107 | aViewCnt[view[2]] = av 108 | pViewCnt[view[2]] = pv 109 | } 110 | 111 | // Return average, std 112 | func computeView(view map[string]int) (float64, float64) { 113 | node := 0 114 | total := 0 115 | for _, v := range view { 116 | node++ 117 | total = total + v 118 | } 119 | avg := float64(total) / float64(node) 120 | 121 | varstd := 0.0 122 | for _, v := range view { 123 | varstd = varstd + (float64(v)-avg)*(float64(v)-avg) 124 | } 125 | varstd = varstd / float64(node) 126 | std := math.Sqrt(varstd) 127 | return avg, std 128 | } 129 | 130 | func init() { 131 | flag.StringVar(&hostport, "hostport", ":11000", "The server's address") 132 | flag.BoolVar(&testSerf, "testserf", false, "If testing serf") 133 | } 134 | 135 | func main() { 136 | flag.Parse() 137 | 138 | fmt.Println("Start server...") 139 | http.HandleFunc("/start", handleStart) 140 | http.HandleFunc("/received", handleReceived) 141 | http.HandleFunc("/query", handleQuery) 142 | http.HandleFunc("/view", handleView) 143 | 144 | if err := http.ListenAndServe(hostport, nil); err != nil { 145 | fmt.Println(err) 146 | } 147 | } 148 | --------------------------------------------------------------------------------