github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/cmd/networkdb-test/dbclient/ndbClient.go (about) 1 package dbclient 2 3 import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "log" 8 "net" 9 "net/http" 10 "os" 11 "regexp" 12 "strconv" 13 "strings" 14 "time" 15 16 "github.com/sirupsen/logrus" 17 ) 18 19 var servicePort string 20 21 const totalWrittenKeys string = "totalKeys" 22 23 type resultTuple struct { 24 id string 25 result int 26 } 27 28 func httpGetFatalError(ip, port, path string) { 29 body, err := httpGet(ip, port, path) 30 if err != nil || !strings.Contains(string(body), "OK") { 31 log.Fatalf("[%s] error %s %s", path, err, body) 32 } 33 } 34 35 func httpGet(ip, port, path string) ([]byte, error) { 36 resp, err := http.Get("http://" + ip + ":" + port + path) 37 if err != nil { 38 logrus.Errorf("httpGet error:%s", err) 39 return nil, err 40 } 41 defer resp.Body.Close() 42 body, err := ioutil.ReadAll(resp.Body) 43 return body, err 44 } 45 46 func joinCluster(ip, port string, members []string, doneCh chan resultTuple) { 47 httpGetFatalError(ip, port, "/join?members="+strings.Join(members, ",")) 48 49 if doneCh != nil { 50 doneCh <- resultTuple{id: ip, result: 0} 51 } 52 } 53 54 func joinNetwork(ip, port, network string, doneCh chan resultTuple) { 55 httpGetFatalError(ip, port, "/joinnetwork?nid="+network) 56 57 if doneCh != nil { 58 doneCh <- resultTuple{id: ip, result: 0} 59 } 60 } 61 62 func leaveNetwork(ip, port, network string, doneCh chan resultTuple) { 63 httpGetFatalError(ip, port, "/leavenetwork?nid="+network) 64 65 if doneCh != nil { 66 doneCh <- resultTuple{id: ip, result: 0} 67 } 68 } 69 70 func writeTableKey(ip, port, networkName, tableName, key string) { 71 createPath := "/createentry?unsafe&nid=" + networkName + "&tname=" + tableName + "&value=v&key=" 72 httpGetFatalError(ip, port, createPath+key) 73 } 74 75 func deleteTableKey(ip, port, networkName, tableName, key string) { 76 deletePath := "/deleteentry?nid=" + networkName + "&tname=" + tableName + "&key=" 77 httpGetFatalError(ip, port, deletePath+key) 78 } 79 80 func clusterPeersNumber(ip, port string, doneCh chan resultTuple) { 81 body, err := httpGet(ip, port, "/clusterpeers") 82 83 if err != nil { 84 logrus.Errorf("clusterPeers %s there was an error: %s", ip, err) 85 doneCh <- resultTuple{id: ip, result: -1} 86 return 87 } 88 peersRegexp := regexp.MustCompile(`total entries: ([0-9]+)`) 89 peersNum, _ := strconv.Atoi(peersRegexp.FindStringSubmatch(string(body))[1]) 90 91 doneCh <- resultTuple{id: ip, result: peersNum} 92 } 93 94 func networkPeersNumber(ip, port, networkName string, doneCh chan resultTuple) { 95 body, err := httpGet(ip, port, "/networkpeers?nid="+networkName) 96 97 if err != nil { 98 logrus.Errorf("networkPeersNumber %s there was an error: %s", ip, err) 99 doneCh <- resultTuple{id: ip, result: -1} 100 return 101 } 102 peersRegexp := regexp.MustCompile(`total entries: ([0-9]+)`) 103 peersNum, _ := strconv.Atoi(peersRegexp.FindStringSubmatch(string(body))[1]) 104 105 doneCh <- resultTuple{id: ip, result: peersNum} 106 } 107 108 func dbTableEntriesNumber(ip, port, networkName, tableName string, doneCh chan resultTuple) { 109 body, err := httpGet(ip, port, "/gettable?nid="+networkName+"&tname="+tableName) 110 111 if err != nil { 112 logrus.Errorf("tableEntriesNumber %s there was an error: %s", ip, err) 113 doneCh <- resultTuple{id: ip, result: -1} 114 return 115 } 116 elementsRegexp := regexp.MustCompile(`total entries: ([0-9]+)`) 117 entriesNum, _ := strconv.Atoi(elementsRegexp.FindStringSubmatch(string(body))[1]) 118 doneCh <- resultTuple{id: ip, result: entriesNum} 119 } 120 121 func dbEntriesNumber(ip, port, networkName string, doneCh chan resultTuple) { 122 body, err := httpGet(ip, port, "/networkstats?nid="+networkName) 123 124 if err != nil { 125 logrus.Errorf("entriesNumber %s there was an error: %s", ip, err) 126 doneCh <- resultTuple{id: ip, result: -1} 127 return 128 } 129 elementsRegexp := regexp.MustCompile(`entries: ([0-9]+)`) 130 entriesNum, _ := strconv.Atoi(elementsRegexp.FindStringSubmatch(string(body))[1]) 131 doneCh <- resultTuple{id: ip, result: entriesNum} 132 } 133 134 func dbQueueLength(ip, port, networkName string, doneCh chan resultTuple) { 135 body, err := httpGet(ip, port, "/networkstats?nid="+networkName) 136 137 if err != nil { 138 logrus.Errorf("queueLength %s there was an error: %s", ip, err) 139 doneCh <- resultTuple{id: ip, result: -1} 140 return 141 } 142 elementsRegexp := regexp.MustCompile(`qlen: ([0-9]+)`) 143 entriesNum, _ := strconv.Atoi(elementsRegexp.FindStringSubmatch(string(body))[1]) 144 doneCh <- resultTuple{id: ip, result: entriesNum} 145 } 146 147 func clientWatchTable(ip, port, networkName, tableName string, doneCh chan resultTuple) { 148 httpGetFatalError(ip, port, "/watchtable?nid="+networkName+"&tname="+tableName) 149 if doneCh != nil { 150 doneCh <- resultTuple{id: ip, result: 0} 151 } 152 } 153 154 func clientTableEntriesNumber(ip, port, networkName, tableName string, doneCh chan resultTuple) { 155 body, err := httpGet(ip, port, "/watchedtableentries?nid="+networkName+"&tname="+tableName) 156 157 if err != nil { 158 logrus.Errorf("clientTableEntriesNumber %s there was an error: %s", ip, err) 159 doneCh <- resultTuple{id: ip, result: -1} 160 return 161 } 162 elementsRegexp := regexp.MustCompile(`total elements: ([0-9]+)`) 163 entriesNum, _ := strconv.Atoi(elementsRegexp.FindStringSubmatch(string(body))[1]) 164 doneCh <- resultTuple{id: ip, result: entriesNum} 165 } 166 167 func writeKeysNumber(ip, port, networkName, tableName, key string, number int, doneCh chan resultTuple) { 168 x := 0 169 for ; x < number; x++ { 170 k := key + strconv.Itoa(x) 171 // write key 172 writeTableKey(ip, port, networkName, tableName, k) 173 } 174 doneCh <- resultTuple{id: ip, result: x} 175 } 176 177 func deleteKeysNumber(ip, port, networkName, tableName, key string, number int, doneCh chan resultTuple) { 178 x := 0 179 for ; x < number; x++ { 180 k := key + strconv.Itoa(x) 181 // write key 182 deleteTableKey(ip, port, networkName, tableName, k) 183 } 184 doneCh <- resultTuple{id: ip, result: x} 185 } 186 187 func writeUniqueKeys(ctx context.Context, ip, port, networkName, tableName, key string, doneCh chan resultTuple) { 188 for x := 0; ; x++ { 189 select { 190 case <-ctx.Done(): 191 doneCh <- resultTuple{id: ip, result: x} 192 return 193 default: 194 k := key + strconv.Itoa(x) 195 // write key 196 writeTableKey(ip, port, networkName, tableName, k) 197 // give time to send out key writes 198 time.Sleep(100 * time.Millisecond) 199 } 200 } 201 } 202 203 func writeDeleteUniqueKeys(ctx context.Context, ip, port, networkName, tableName, key string, doneCh chan resultTuple) { 204 for x := 0; ; x++ { 205 select { 206 case <-ctx.Done(): 207 doneCh <- resultTuple{id: ip, result: x} 208 return 209 default: 210 k := key + strconv.Itoa(x) 211 // write key 212 writeTableKey(ip, port, networkName, tableName, k) 213 // give time to send out key writes 214 time.Sleep(100 * time.Millisecond) 215 // delete key 216 deleteTableKey(ip, port, networkName, tableName, k) 217 } 218 } 219 } 220 221 func writeDeleteLeaveJoin(ctx context.Context, ip, port, networkName, tableName, key string, doneCh chan resultTuple) { 222 for x := 0; ; x++ { 223 select { 224 case <-ctx.Done(): 225 doneCh <- resultTuple{id: ip, result: x} 226 return 227 default: 228 k := key + strconv.Itoa(x) 229 // write key 230 writeTableKey(ip, port, networkName, tableName, k) 231 time.Sleep(100 * time.Millisecond) 232 // delete key 233 deleteTableKey(ip, port, networkName, tableName, k) 234 // give some time 235 time.Sleep(100 * time.Millisecond) 236 // leave network 237 leaveNetwork(ip, port, networkName, nil) 238 // join network 239 joinNetwork(ip, port, networkName, nil) 240 } 241 } 242 } 243 244 func ready(ip, port string, doneCh chan resultTuple) { 245 for { 246 body, err := httpGet(ip, port, "/ready") 247 if err != nil || !strings.Contains(string(body), "OK") { 248 time.Sleep(500 * time.Millisecond) 249 continue 250 } 251 // success 252 break 253 } 254 // notify the completion 255 doneCh <- resultTuple{id: ip, result: 0} 256 } 257 258 func checkTable(ctx context.Context, ips []string, port, networkName, tableName string, expectedEntries int, fn func(string, string, string, string, chan resultTuple)) (opTime time.Duration) { 259 startTime := time.Now().UnixNano() 260 var successTime int64 261 262 // Loop for 2 minutes to guarantee that the result is stable 263 for { 264 select { 265 case <-ctx.Done(): 266 // Validate test success, if the time is set means that all the tables are empty 267 if successTime != 0 { 268 opTime = time.Duration(successTime-startTime) / time.Millisecond 269 logrus.Infof("Check table passed, the cluster converged in %d msec", opTime) 270 return 271 } 272 log.Fatal("Test failed, there is still entries in the tables of the nodes") 273 default: 274 logrus.Infof("Checking table %s expected %d", tableName, expectedEntries) 275 doneCh := make(chan resultTuple, len(ips)) 276 for _, ip := range ips { 277 go fn(ip, servicePort, networkName, tableName, doneCh) 278 } 279 280 nodesWithCorrectEntriesNum := 0 281 for i := len(ips); i > 0; i-- { 282 tableEntries := <-doneCh 283 logrus.Infof("Node %s has %d entries", tableEntries.id, tableEntries.result) 284 if tableEntries.result == expectedEntries { 285 nodesWithCorrectEntriesNum++ 286 } 287 } 288 close(doneCh) 289 if nodesWithCorrectEntriesNum == len(ips) { 290 if successTime == 0 { 291 successTime = time.Now().UnixNano() 292 logrus.Infof("Success after %d msec", time.Duration(successTime-startTime)/time.Millisecond) 293 } 294 } else { 295 successTime = 0 296 } 297 time.Sleep(10 * time.Second) 298 } 299 } 300 } 301 302 func waitWriters(parallelWriters int, mustWrite bool, doneCh chan resultTuple) map[string]int { 303 var totalKeys int 304 resultTable := make(map[string]int) 305 for i := 0; i < parallelWriters; i++ { 306 logrus.Infof("Waiting for %d workers", parallelWriters-i) 307 workerReturn := <-doneCh 308 totalKeys += workerReturn.result 309 if mustWrite && workerReturn.result == 0 { 310 log.Fatalf("The worker %s did not write any key %d == 0", workerReturn.id, workerReturn.result) 311 } 312 if !mustWrite && workerReturn.result != 0 { 313 log.Fatalf("The worker %s was supposed to return 0 instead %d != 0", workerReturn.id, workerReturn.result) 314 } 315 if mustWrite { 316 resultTable[workerReturn.id] = workerReturn.result 317 logrus.Infof("The worker %s wrote %d keys", workerReturn.id, workerReturn.result) 318 } 319 } 320 resultTable[totalWrittenKeys] = totalKeys 321 return resultTable 322 } 323 324 // ready 325 func doReady(ips []string) { 326 doneCh := make(chan resultTuple, len(ips)) 327 // check all the nodes 328 for _, ip := range ips { 329 go ready(ip, servicePort, doneCh) 330 } 331 // wait for the readiness of all nodes 332 for i := len(ips); i > 0; i-- { 333 <-doneCh 334 } 335 close(doneCh) 336 } 337 338 // join 339 func doJoin(ips []string) { 340 doneCh := make(chan resultTuple, len(ips)) 341 // check all the nodes 342 for i, ip := range ips { 343 members := append([]string(nil), ips[:i]...) 344 members = append(members, ips[i+1:]...) 345 go joinCluster(ip, servicePort, members, doneCh) 346 } 347 // wait for the readiness of all nodes 348 for i := len(ips); i > 0; i-- { 349 <-doneCh 350 } 351 close(doneCh) 352 } 353 354 // cluster-peers expectedNumberPeers maxRetry 355 func doClusterPeers(ips []string, args []string) { 356 doneCh := make(chan resultTuple, len(ips)) 357 expectedPeers, _ := strconv.Atoi(args[0]) 358 maxRetry, _ := strconv.Atoi(args[1]) 359 for retry := 0; retry < maxRetry; retry++ { 360 // check all the nodes 361 for _, ip := range ips { 362 go clusterPeersNumber(ip, servicePort, doneCh) 363 } 364 var failed bool 365 // wait for the readiness of all nodes 366 for i := len(ips); i > 0; i-- { 367 node := <-doneCh 368 if node.result != expectedPeers { 369 failed = true 370 if retry == maxRetry-1 { 371 log.Fatalf("Expected peers from %s mismatch %d != %d", node.id, expectedPeers, node.result) 372 } else { 373 logrus.Warnf("Expected peers from %s mismatch %d != %d", node.id, expectedPeers, node.result) 374 } 375 time.Sleep(1 * time.Second) 376 } 377 } 378 // check if needs retry 379 if !failed { 380 break 381 } 382 } 383 close(doneCh) 384 } 385 386 // join-network networkName 387 func doJoinNetwork(ips []string, args []string) { 388 doneCh := make(chan resultTuple, len(ips)) 389 // check all the nodes 390 for _, ip := range ips { 391 go joinNetwork(ip, servicePort, args[0], doneCh) 392 } 393 // wait for the readiness of all nodes 394 for i := len(ips); i > 0; i-- { 395 <-doneCh 396 } 397 close(doneCh) 398 } 399 400 // leave-network networkName 401 func doLeaveNetwork(ips []string, args []string) { 402 doneCh := make(chan resultTuple, len(ips)) 403 // check all the nodes 404 for _, ip := range ips { 405 go leaveNetwork(ip, servicePort, args[0], doneCh) 406 } 407 // wait for the readiness of all nodes 408 for i := len(ips); i > 0; i-- { 409 <-doneCh 410 } 411 close(doneCh) 412 } 413 414 // network-peers networkName expectedNumberPeers maxRetry 415 func doNetworkPeers(ips []string, args []string) { 416 doneCh := make(chan resultTuple, len(ips)) 417 networkName := args[0] 418 expectedPeers, _ := strconv.Atoi(args[1]) 419 maxRetry, _ := strconv.Atoi(args[2]) 420 for retry := 0; retry < maxRetry; retry++ { 421 // check all the nodes 422 for _, ip := range ips { 423 go networkPeersNumber(ip, servicePort, networkName, doneCh) 424 } 425 var failed bool 426 // wait for the readiness of all nodes 427 for i := len(ips); i > 0; i-- { 428 node := <-doneCh 429 if node.result != expectedPeers { 430 failed = true 431 if retry == maxRetry-1 { 432 log.Fatalf("Expected peers from %s mismatch %d != %d", node.id, expectedPeers, node.result) 433 } else { 434 logrus.Warnf("Expected peers from %s mismatch %d != %d", node.id, expectedPeers, node.result) 435 } 436 time.Sleep(1 * time.Second) 437 } 438 } 439 // check if needs retry 440 if !failed { 441 break 442 } 443 } 444 close(doneCh) 445 } 446 447 // network-stats-queue networkName <gt/lt> queueSize 448 func doNetworkStatsQueue(ips []string, args []string) { 449 doneCh := make(chan resultTuple, len(ips)) 450 networkName := args[0] 451 comparison := args[1] 452 size, _ := strconv.Atoi(args[2]) 453 454 // check all the nodes 455 for _, ip := range ips { 456 go dbQueueLength(ip, servicePort, networkName, doneCh) 457 } 458 459 var avgQueueSize int 460 // wait for the readiness of all nodes 461 for i := len(ips); i > 0; i-- { 462 node := <-doneCh 463 switch comparison { 464 case "lt": 465 if node.result > size { 466 log.Fatalf("Expected queue size from %s to be %d < %d", node.id, node.result, size) 467 } 468 case "gt": 469 if node.result < size { 470 log.Fatalf("Expected queue size from %s to be %d > %d", node.id, node.result, size) 471 } 472 default: 473 log.Fatal("unknown comparison operator") 474 } 475 avgQueueSize += node.result 476 } 477 close(doneCh) 478 avgQueueSize /= len(ips) 479 fmt.Fprintf(os.Stderr, "doNetworkStatsQueue succeeded with avg queue:%d", avgQueueSize) 480 } 481 482 // write-keys networkName tableName parallelWriters numberOfKeysEach 483 func doWriteKeys(ips []string, args []string) { 484 networkName := args[0] 485 tableName := args[1] 486 parallelWriters, _ := strconv.Atoi(args[2]) 487 numberOfKeys, _ := strconv.Atoi(args[3]) 488 489 doneCh := make(chan resultTuple, parallelWriters) 490 // Enable watch of tables from clients 491 for i := 0; i < parallelWriters; i++ { 492 go clientWatchTable(ips[i], servicePort, networkName, tableName, doneCh) 493 } 494 waitWriters(parallelWriters, false, doneCh) 495 496 // Start parallel writers that will create and delete unique keys 497 defer close(doneCh) 498 for i := 0; i < parallelWriters; i++ { 499 key := "key-" + strconv.Itoa(i) + "-" 500 logrus.Infof("Spawn worker: %d on IP:%s", i, ips[i]) 501 go writeKeysNumber(ips[i], servicePort, networkName, tableName, key, numberOfKeys, doneCh) 502 } 503 504 // Sync with all the writers 505 keyMap := waitWriters(parallelWriters, true, doneCh) 506 logrus.Infof("Written a total of %d keys on the cluster", keyMap[totalWrittenKeys]) 507 508 // check table entries for 2 minutes 509 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) 510 opTime := checkTable(ctx, ips, servicePort, networkName, tableName, keyMap[totalWrittenKeys], dbTableEntriesNumber) 511 cancel() 512 fmt.Fprintf(os.Stderr, "doWriteKeys succeeded in %d msec", opTime) 513 } 514 515 // delete-keys networkName tableName parallelWriters numberOfKeysEach 516 func doDeleteKeys(ips []string, args []string) { 517 networkName := args[0] 518 tableName := args[1] 519 parallelWriters, _ := strconv.Atoi(args[2]) 520 numberOfKeys, _ := strconv.Atoi(args[3]) 521 522 doneCh := make(chan resultTuple, parallelWriters) 523 // Enable watch of tables from clients 524 for i := 0; i < parallelWriters; i++ { 525 go clientWatchTable(ips[i], servicePort, networkName, tableName, doneCh) 526 } 527 waitWriters(parallelWriters, false, doneCh) 528 529 // Start parallel writers that will create and delete unique keys 530 defer close(doneCh) 531 for i := 0; i < parallelWriters; i++ { 532 key := "key-" + strconv.Itoa(i) + "-" 533 logrus.Infof("Spawn worker: %d on IP:%s", i, ips[i]) 534 go deleteKeysNumber(ips[i], servicePort, networkName, tableName, key, numberOfKeys, doneCh) 535 } 536 537 // Sync with all the writers 538 keyMap := waitWriters(parallelWriters, true, doneCh) 539 logrus.Infof("Written a total of %d keys on the cluster", keyMap[totalWrittenKeys]) 540 541 // check table entries for 2 minutes 542 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) 543 opTime := checkTable(ctx, ips, servicePort, networkName, tableName, 0, dbTableEntriesNumber) 544 cancel() 545 fmt.Fprintf(os.Stderr, "doDeletekeys succeeded in %d msec", opTime) 546 } 547 548 // write-delete-unique-keys networkName tableName numParallelWriters writeTimeSec 549 func doWriteDeleteUniqueKeys(ips []string, args []string) { 550 networkName := args[0] 551 tableName := args[1] 552 parallelWriters, _ := strconv.Atoi(args[2]) 553 writeTimeSec, _ := strconv.Atoi(args[3]) 554 555 doneCh := make(chan resultTuple, parallelWriters) 556 // Enable watch of tables from clients 557 for i := 0; i < parallelWriters; i++ { 558 go clientWatchTable(ips[i], servicePort, networkName, tableName, doneCh) 559 } 560 waitWriters(parallelWriters, false, doneCh) 561 562 // Start parallel writers that will create and delete unique keys 563 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(writeTimeSec)*time.Second) 564 for i := 0; i < parallelWriters; i++ { 565 key := "key-" + strconv.Itoa(i) + "-" 566 logrus.Infof("Spawn worker: %d on IP:%s", i, ips[i]) 567 go writeDeleteUniqueKeys(ctx, ips[i], servicePort, networkName, tableName, key, doneCh) 568 } 569 570 // Sync with all the writers 571 keyMap := waitWriters(parallelWriters, true, doneCh) 572 cancel() 573 logrus.Infof("Written a total of %d keys on the cluster", keyMap[totalWrittenKeys]) 574 575 // check table entries for 2 minutes 576 ctx, cancel = context.WithTimeout(context.Background(), 2*time.Minute) 577 opDBTime := checkTable(ctx, ips, servicePort, networkName, tableName, 0, dbTableEntriesNumber) 578 cancel() 579 ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) 580 opClientTime := checkTable(ctx, ips, servicePort, networkName, tableName, 0, clientTableEntriesNumber) 581 cancel() 582 fmt.Fprintf(os.Stderr, "doWriteDeleteUniqueKeys succeeded in %d msec and client %d msec", opDBTime, opClientTime) 583 } 584 585 // write-unique-keys networkName tableName numParallelWriters writeTimeSec 586 func doWriteUniqueKeys(ips []string, args []string) { 587 networkName := args[0] 588 tableName := args[1] 589 parallelWriters, _ := strconv.Atoi(args[2]) 590 writeTimeSec, _ := strconv.Atoi(args[3]) 591 592 doneCh := make(chan resultTuple, parallelWriters) 593 // Enable watch of tables from clients 594 for i := 0; i < parallelWriters; i++ { 595 go clientWatchTable(ips[i], servicePort, networkName, tableName, doneCh) 596 } 597 waitWriters(parallelWriters, false, doneCh) 598 599 // Start parallel writers that will create and delete unique keys 600 defer close(doneCh) 601 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(writeTimeSec)*time.Second) 602 for i := 0; i < parallelWriters; i++ { 603 key := "key-" + strconv.Itoa(i) + "-" 604 logrus.Infof("Spawn worker: %d on IP:%s", i, ips[i]) 605 go writeUniqueKeys(ctx, ips[i], servicePort, networkName, tableName, key, doneCh) 606 } 607 608 // Sync with all the writers 609 keyMap := waitWriters(parallelWriters, true, doneCh) 610 cancel() 611 logrus.Infof("Written a total of %d keys on the cluster", keyMap[totalWrittenKeys]) 612 613 // check table entries for 2 minutes 614 ctx, cancel = context.WithTimeout(context.Background(), 2*time.Minute) 615 opTime := checkTable(ctx, ips, servicePort, networkName, tableName, keyMap[totalWrittenKeys], dbTableEntriesNumber) 616 cancel() 617 fmt.Fprintf(os.Stderr, "doWriteUniqueKeys succeeded in %d msec", opTime) 618 } 619 620 // write-delete-leave-join networkName tableName numParallelWriters writeTimeSec 621 func doWriteDeleteLeaveJoin(ips []string, args []string) { 622 networkName := args[0] 623 tableName := args[1] 624 parallelWriters, _ := strconv.Atoi(args[2]) 625 writeTimeSec, _ := strconv.Atoi(args[3]) 626 627 // Start parallel writers that will create and delete unique keys 628 doneCh := make(chan resultTuple, parallelWriters) 629 defer close(doneCh) 630 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(writeTimeSec)*time.Second) 631 for i := 0; i < parallelWriters; i++ { 632 key := "key-" + strconv.Itoa(i) + "-" 633 logrus.Infof("Spawn worker: %d on IP:%s", i, ips[i]) 634 go writeDeleteLeaveJoin(ctx, ips[i], servicePort, networkName, tableName, key, doneCh) 635 } 636 637 // Sync with all the writers 638 keyMap := waitWriters(parallelWriters, true, doneCh) 639 cancel() 640 logrus.Infof("Written a total of %d keys on the cluster", keyMap["totalKeys"]) 641 642 // check table entries for 2 minutes 643 ctx, cancel = context.WithTimeout(context.Background(), 2*time.Minute) 644 opTime := checkTable(ctx, ips, servicePort, networkName, tableName, 0, dbTableEntriesNumber) 645 cancel() 646 fmt.Fprintf(os.Stderr, "doWriteDeleteLeaveJoin succeeded in %d msec", opTime) 647 } 648 649 // write-delete-wait-leave-join networkName tableName numParallelWriters writeTimeSec 650 func doWriteDeleteWaitLeaveJoin(ips []string, args []string) { 651 networkName := args[0] 652 tableName := args[1] 653 parallelWriters, _ := strconv.Atoi(args[2]) 654 writeTimeSec, _ := strconv.Atoi(args[3]) 655 656 // Start parallel writers that will create and delete unique keys 657 doneCh := make(chan resultTuple, parallelWriters) 658 defer close(doneCh) 659 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(writeTimeSec)*time.Second) 660 for i := 0; i < parallelWriters; i++ { 661 key := "key-" + strconv.Itoa(i) + "-" 662 logrus.Infof("Spawn worker: %d on IP:%s", i, ips[i]) 663 go writeDeleteUniqueKeys(ctx, ips[i], servicePort, networkName, tableName, key, doneCh) 664 } 665 666 // Sync with all the writers 667 keyMap := waitWriters(parallelWriters, true, doneCh) 668 cancel() 669 logrus.Infof("Written a total of %d keys on the cluster", keyMap[totalWrittenKeys]) 670 671 // The writers will leave the network 672 for i := 0; i < parallelWriters; i++ { 673 logrus.Infof("worker leaveNetwork: %d on IP:%s", i, ips[i]) 674 go leaveNetwork(ips[i], servicePort, networkName, doneCh) 675 } 676 waitWriters(parallelWriters, false, doneCh) 677 678 // Give some time 679 time.Sleep(100 * time.Millisecond) 680 681 // The writers will join the network 682 for i := 0; i < parallelWriters; i++ { 683 logrus.Infof("worker joinNetwork: %d on IP:%s", i, ips[i]) 684 go joinNetwork(ips[i], servicePort, networkName, doneCh) 685 } 686 waitWriters(parallelWriters, false, doneCh) 687 688 // check table entries for 2 minutes 689 ctx, cancel = context.WithTimeout(context.Background(), 2*time.Minute) 690 opTime := checkTable(ctx, ips, servicePort, networkName, tableName, 0, dbTableEntriesNumber) 691 cancel() 692 fmt.Fprintf(os.Stderr, "doWriteDeleteWaitLeaveJoin succeeded in %d msec", opTime) 693 } 694 695 // write-wait-leave networkName tableName numParallelWriters writeTimeSec 696 func doWriteWaitLeave(ips []string, args []string) { 697 networkName := args[0] 698 tableName := args[1] 699 parallelWriters, _ := strconv.Atoi(args[2]) 700 writeTimeSec, _ := strconv.Atoi(args[3]) 701 702 // Start parallel writers that will create and delete unique keys 703 doneCh := make(chan resultTuple, parallelWriters) 704 defer close(doneCh) 705 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(writeTimeSec)*time.Second) 706 for i := 0; i < parallelWriters; i++ { 707 key := "key-" + strconv.Itoa(i) + "-" 708 logrus.Infof("Spawn worker: %d on IP:%s", i, ips[i]) 709 go writeUniqueKeys(ctx, ips[i], servicePort, networkName, tableName, key, doneCh) 710 } 711 712 // Sync with all the writers 713 keyMap := waitWriters(parallelWriters, true, doneCh) 714 cancel() 715 logrus.Infof("Written a total of %d keys on the cluster", keyMap[totalWrittenKeys]) 716 717 // The writers will leave the network 718 for i := 0; i < parallelWriters; i++ { 719 logrus.Infof("worker leaveNetwork: %d on IP:%s", i, ips[i]) 720 go leaveNetwork(ips[i], servicePort, networkName, doneCh) 721 } 722 waitWriters(parallelWriters, false, doneCh) 723 724 // check table entries for 2 minutes 725 ctx, cancel = context.WithTimeout(context.Background(), 2*time.Minute) 726 opTime := checkTable(ctx, ips, servicePort, networkName, tableName, 0, dbTableEntriesNumber) 727 cancel() 728 fmt.Fprintf(os.Stderr, "doWriteLeaveJoin succeeded in %d msec", opTime) 729 } 730 731 // write-wait-leave-join networkName tableName numParallelWriters writeTimeSec numParallelLeaver 732 func doWriteWaitLeaveJoin(ips []string, args []string) { 733 networkName := args[0] 734 tableName := args[1] 735 parallelWriters, _ := strconv.Atoi(args[2]) 736 writeTimeSec, _ := strconv.Atoi(args[3]) 737 parallelLeaver, _ := strconv.Atoi(args[4]) 738 739 // Start parallel writers that will create and delete unique keys 740 doneCh := make(chan resultTuple, parallelWriters) 741 defer close(doneCh) 742 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(writeTimeSec)*time.Second) 743 for i := 0; i < parallelWriters; i++ { 744 key := "key-" + strconv.Itoa(i) + "-" 745 logrus.Infof("Spawn worker: %d on IP:%s", i, ips[i]) 746 go writeUniqueKeys(ctx, ips[i], servicePort, networkName, tableName, key, doneCh) 747 } 748 749 // Sync with all the writers 750 keyMap := waitWriters(parallelWriters, true, doneCh) 751 cancel() 752 logrus.Infof("Written a total of %d keys on the cluster", keyMap[totalWrittenKeys]) 753 754 keysExpected := keyMap[totalWrittenKeys] 755 // The Leavers will leave the network 756 for i := 0; i < parallelLeaver; i++ { 757 logrus.Infof("worker leaveNetwork: %d on IP:%s", i, ips[i]) 758 go leaveNetwork(ips[i], servicePort, networkName, doneCh) 759 // Once a node leave all the keys written previously will be deleted, so the expected keys will consider that as removed 760 keysExpected -= keyMap[ips[i]] 761 } 762 waitWriters(parallelLeaver, false, doneCh) 763 764 // Give some time 765 time.Sleep(100 * time.Millisecond) 766 767 // The writers will join the network 768 for i := 0; i < parallelLeaver; i++ { 769 logrus.Infof("worker joinNetwork: %d on IP:%s", i, ips[i]) 770 go joinNetwork(ips[i], servicePort, networkName, doneCh) 771 } 772 waitWriters(parallelLeaver, false, doneCh) 773 774 // check table entries for 2 minutes 775 ctx, cancel = context.WithTimeout(context.Background(), 2*time.Minute) 776 opTime := checkTable(ctx, ips, servicePort, networkName, tableName, keysExpected, dbTableEntriesNumber) 777 cancel() 778 fmt.Fprintf(os.Stderr, "doWriteWaitLeaveJoin succeeded in %d msec", opTime) 779 } 780 781 var cmdArgChec = map[string]int{ 782 "debug": 0, 783 "fail": 0, 784 "ready": 2, 785 "join": 2, 786 "leave": 2, 787 "join-network": 3, 788 "leave-network": 3, 789 "cluster-peers": 5, 790 "network-peers": 5, 791 "write-delete-unique-keys": 7, 792 } 793 794 // Client is a client 795 func Client(args []string) { 796 logrus.Infof("[CLIENT] Starting with arguments %v", args) 797 command := args[0] 798 799 if len(args) < cmdArgChec[command] { 800 log.Fatalf("Command %s requires %d arguments, passed %d, aborting...", command, cmdArgChec[command], len(args)) 801 } 802 803 switch command { 804 case "debug": 805 time.Sleep(1 * time.Hour) 806 os.Exit(0) 807 case "fail": 808 log.Fatalf("Test error condition with message: error error error") 809 } 810 811 serviceName := args[1] 812 ips, _ := net.LookupHost("tasks." + serviceName) 813 logrus.Infof("got the ips %v", ips) 814 if len(ips) == 0 { 815 log.Fatalf("Cannot resolve any IP for the service tasks.%s", serviceName) 816 } 817 servicePort = args[2] 818 commandArgs := args[3:] 819 logrus.Infof("Executing %s with args:%v", command, commandArgs) 820 switch command { 821 case "ready": 822 doReady(ips) 823 case "join": 824 doJoin(ips) 825 case "leave": 826 827 case "cluster-peers": 828 // cluster-peers maxRetry 829 doClusterPeers(ips, commandArgs) 830 831 case "join-network": 832 // join-network networkName 833 doJoinNetwork(ips, commandArgs) 834 case "leave-network": 835 // leave-network networkName 836 doLeaveNetwork(ips, commandArgs) 837 case "network-peers": 838 // network-peers networkName expectedNumberPeers maxRetry 839 doNetworkPeers(ips, commandArgs) 840 // case "network-stats-entries": 841 // // network-stats-entries networkName maxRetry 842 // doNetworkPeers(ips, commandArgs) 843 case "network-stats-queue": 844 // network-stats-queue networkName <lt/gt> queueSize 845 doNetworkStatsQueue(ips, commandArgs) 846 847 case "write-keys": 848 // write-keys networkName tableName parallelWriters numberOfKeysEach 849 doWriteKeys(ips, commandArgs) 850 case "delete-keys": 851 // delete-keys networkName tableName parallelWriters numberOfKeysEach 852 doDeleteKeys(ips, commandArgs) 853 case "write-unique-keys": 854 // write-delete-unique-keys networkName tableName numParallelWriters writeTimeSec 855 doWriteUniqueKeys(ips, commandArgs) 856 case "write-delete-unique-keys": 857 // write-delete-unique-keys networkName tableName numParallelWriters writeTimeSec 858 doWriteDeleteUniqueKeys(ips, commandArgs) 859 case "write-delete-leave-join": 860 // write-delete-leave-join networkName tableName numParallelWriters writeTimeSec 861 doWriteDeleteLeaveJoin(ips, commandArgs) 862 case "write-delete-wait-leave-join": 863 // write-delete-wait-leave-join networkName tableName numParallelWriters writeTimeSec 864 doWriteDeleteWaitLeaveJoin(ips, commandArgs) 865 case "write-wait-leave": 866 // write-wait-leave networkName tableName numParallelWriters writeTimeSec 867 doWriteWaitLeave(ips, commandArgs) 868 case "write-wait-leave-join": 869 // write-wait-leave networkName tableName numParallelWriters writeTimeSec 870 doWriteWaitLeaveJoin(ips, commandArgs) 871 default: 872 log.Fatalf("Command %s not recognized", command) 873 } 874 }