diff --git a/cmd/devp2p/dns_route53.go b/cmd/devp2p/dns_route53.go index 71118be543..c5f99529b8 100644 --- a/cmd/devp2p/dns_route53.go +++ b/cmd/devp2p/dns_route53.go @@ -32,9 +32,13 @@ import ( "gopkg.in/urfave/cli.v1" ) -// The Route53 limits change sets to this size. DNS changes need to be split -// up into multiple batches to work around the limit. -const route53ChangeLimit = 30000 +const ( + // Route53 limits change sets to 32k of 'RDATA size'. Change sets are also limited to + // 1000 items. UPSERTs count double. + // https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests-changeresourcerecordsets + route53ChangeSizeLimit = 32000 + route53ChangeCountLimit = 1000 +) var ( route53AccessKeyFlag = cli.StringFlag{ @@ -102,7 +106,7 @@ func (c *route53Client) deploy(name string, t *dnsdisc.Tree) error { } // Submit change batches. - batches := splitChanges(changes, route53ChangeLimit) + batches := splitChanges(changes, route53ChangeSizeLimit, route53ChangeCountLimit) for i, changes := range batches { log.Info(fmt.Sprintf("Submitting %d changes to Route53", len(changes))) batch := new(route53.ChangeBatch) @@ -176,7 +180,7 @@ func (c *route53Client) computeChanges(name string, records map[string]string, e // Entry is unknown, push a new one log.Info(fmt.Sprintf("Creating %s = %q", path, val)) changes = append(changes, newTXTChange("CREATE", path, ttl, splitTXT(val))) - } else if prevValue != val { + } else if prevValue != val || prevRecords.ttl != ttl { // Entry already exists, only change its content. log.Info(fmt.Sprintf("Updating %s from %q to %q", path, prevValue, val)) changes = append(changes, newTXTChange("UPSERT", path, ttl, splitTXT(val))) @@ -212,18 +216,26 @@ func sortChanges(changes []*route53.Change) { // splitChanges splits up DNS changes such that each change batch // is smaller than the given RDATA limit. -func splitChanges(changes []*route53.Change, limit int) [][]*route53.Change { - var batches [][]*route53.Change - var batchSize int +func splitChanges(changes []*route53.Change, sizeLimit, countLimit int) [][]*route53.Change { + var ( + batches [][]*route53.Change + batchSize int + batchCount int + ) for _, ch := range changes { // Start new batch if this change pushes the current one over the limit. - size := changeSize(ch) - if len(batches) == 0 || batchSize+size > limit { + count := changeCount(ch) + size := changeSize(ch) * count + overSize := batchSize+size > sizeLimit + overCount := batchCount+count > countLimit + if len(batches) == 0 || overSize || overCount { batches = append(batches, nil) batchSize = 0 + batchCount = 0 } batches[len(batches)-1] = append(batches[len(batches)-1], ch) batchSize += size + batchCount += count } return batches } @@ -239,6 +251,13 @@ func changeSize(ch *route53.Change) int { return size } +func changeCount(ch *route53.Change) int { + if *ch.Action == "UPSERT" { + return 2 + } + return 1 +} + // collectRecords collects all TXT records below the given name. func (c *route53Client) collectRecords(name string) (map[string]recordSet, error) { log.Info(fmt.Sprintf("Retrieving existing TXT records on %s (%s)", name, c.zoneID)) diff --git a/cmd/devp2p/dns_route53_test.go b/cmd/devp2p/dns_route53_test.go index f6ab6c1762..a2ef3791f6 100644 --- a/cmd/devp2p/dns_route53_test.go +++ b/cmd/devp2p/dns_route53_test.go @@ -140,11 +140,23 @@ func TestRoute53ChangeSort(t *testing.T) { t.Fatalf("wrong changes (got %d, want %d)", len(changes), len(wantChanges)) } + // Check splitting according to size. wantSplit := [][]*route53.Change{ wantChanges[:4], - wantChanges[4:8], + wantChanges[4:6], + wantChanges[6:], } - split := splitChanges(changes, 600) + split := splitChanges(changes, 600, 4000) + if !reflect.DeepEqual(split, wantSplit) { + t.Fatalf("wrong split batches: got %d, want %d", len(split), len(wantSplit)) + } + + // Check splitting according to count. + wantSplit = [][]*route53.Change{ + wantChanges[:5], + wantChanges[5:], + } + split = splitChanges(changes, 10000, 6) if !reflect.DeepEqual(split, wantSplit) { t.Fatalf("wrong split batches: got %d, want %d", len(split), len(wantSplit)) } diff --git a/cmd/devp2p/dnscmd.go b/cmd/devp2p/dnscmd.go index 7c9ccd31f4..8ca31504d3 100644 --- a/cmd/devp2p/dnscmd.go +++ b/cmd/devp2p/dnscmd.go @@ -97,8 +97,8 @@ var ( ) const ( - rootTTL = 1 - treeNodeTTL = 2147483647 + rootTTL = 30 * 60 // 30 min + treeNodeTTL = 4 * 7 * 24 * 60 * 60 // 4 weeks ) // dnsSync performs dnsSyncCommand. diff --git a/metrics/cpu.go b/metrics/cpu.go index 3278d81616..72ece16e07 100644 --- a/metrics/cpu.go +++ b/metrics/cpu.go @@ -16,21 +16,9 @@ package metrics -import "github.com/elastic/gosigar" - // CPUStats is the system and process CPU stats. type CPUStats struct { GlobalTime int64 // Time spent by the CPU working on all processes GlobalWait int64 // Time spent by waiting on disk for all processes LocalTime int64 // Time spent by the CPU working on this process } - -// ReadCPUStats retrieves the current CPU stats. -func ReadCPUStats(stats *CPUStats) { - global := gosigar.Cpu{} - global.Get() - - stats.GlobalTime = int64(global.User + global.Nice + global.Sys) - stats.GlobalWait = int64(global.Wait) - stats.LocalTime = getProcessCPUTime() -} diff --git a/metrics/cpu_disabled.go b/metrics/cpu_disabled.go new file mode 100644 index 0000000000..6c3428993f --- /dev/null +++ b/metrics/cpu_disabled.go @@ -0,0 +1,23 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build ios + +package metrics + +// ReadCPUStats retrieves the current CPU stats. Internally this uses `gosigar`, +// which is not supported on the platforms in this file. +func ReadCPUStats(stats *CPUStats) {} diff --git a/metrics/cpu_enabled.go b/metrics/cpu_enabled.go new file mode 100644 index 0000000000..99d44e4002 --- /dev/null +++ b/metrics/cpu_enabled.go @@ -0,0 +1,31 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build !ios + +package metrics + +import "github.com/elastic/gosigar" + +// ReadCPUStats retrieves the current CPU stats. +func ReadCPUStats(stats *CPUStats) { + global := gosigar.Cpu{} + global.Get() + + stats.GlobalTime = int64(global.User + global.Nice + global.Sys) + stats.GlobalWait = int64(global.Wait) + stats.LocalTime = getProcessCPUTime() +}