func()

in go/cmd/ct-fetch/ct-fetch.go [783:853]


func (lw *LogWorker) downloadCTRangeToChannel(ctx context.Context, verifier *CtLogSubtreeVerifier, entryChan chan<- CtLogEntry) (uint64, uint64, error) {
	var minTimestamp uint64
	var maxTimestamp uint64

	b := &backoff.Backoff{
		Jitter: true,
		Min:    5 * time.Second,
		Max:    10 * time.Minute,
	}

	index := verifier.Subtree.First
	last := verifier.Subtree.Last
	for index <= last {
		// TODO(jms) Add an option to get entries from disk.
		resp, err := lw.Client.GetRawEntries(ctx, int64(index), int64(last))
		if err != nil {
			if strings.Contains(err.Error(), "HTTP Status") &&
				(strings.Contains(err.Error(), "429") || strings.Contains(err.Error(), "Too Many Requests")) {
				d := b.Duration()
				glog.Infof("[%s] received status code 429 at index=%d, retrying in %s: %v", lw.Name(), index, d, err)

				time.Sleep(d)
				continue
			}

			glog.Warningf("Failed to get entries: %v", err)
			return minTimestamp, maxTimestamp, err
		}
		b.Reset()

		for _, entry := range resp.Entries {
			logEntry, err := ct.LogEntryFromLeaf(int64(index), &entry)
			if _, ok := err.(x509.NonFatalErrors); !ok && err != nil {
				glog.Warningf("Erroneous certificate: log=%s index=%d err=%v",
					lw.Name(), index, err)

				// This is a serious error that prevents us from ingesting a log, so
				// we ping the `ct-fetch.parse.error` metric to generate an alert and
				// also the `ct-fetch.<log key>.parse.error` metric to identify the log.
				metrics.IncrCounter([]string{"parse", "error"}, 1)
				metrics.IncrCounter([]string{lw.MetricKey, "parse", "error"}, 1)
				index++
				continue
			}

			// We might block while waiting for space in entryChan.
			// If we catch a signal here the verification will fail and the subtree
			// will not get merged.
			select {
			case <-ctx.Done():
				glog.Infof("[%s] Cancelled", lw.Name())
				return minTimestamp, maxTimestamp, nil
			case entryChan <- CtLogEntry{logEntry, lw.LogMeta}:
			}

			// Update the metadata that we will pass to mergeSubtree.
			entryTimestamp := logEntry.Leaf.TimestampedEntry.Timestamp
			if minTimestamp == 0 || entryTimestamp < minTimestamp {
				minTimestamp = entryTimestamp
			}
			if maxTimestamp == 0 || maxTimestamp < entryTimestamp {
				maxTimestamp = entryTimestamp
			}
			verifier.Consume(entry.LeafInput)

			index++
		}
	}

	return minTimestamp, maxTimestamp, nil
}