func (l *Logger) postToLog(p *toPost) {
	l.wg.Add(1)  
	l.toPost <- p
}
postToLog() is used during the initial queueing of chains to avoid spinning
up an excessive number of goroutines, and unecessarily using up memory. If
asyncPostToLog() was called instead, then every time a new chain was queued,
a new goroutine would be created, each holding their own chain - regardless
of whether there were postServers available to process them or not.  If a
large number of chains were queued in a short period of time, this could
lead to a large number of these additional goroutines being created,
resulting in excessive memory usage.
package fixchain
import (
	"context"
	"fmt"
	"log"
	"sync"
	"sync/atomic"
	"time"
	ct "github.com/google/certificate-transparency-go"
	"github.com/google/certificate-transparency-go/client"
	"github.com/google/certificate-transparency-go/x509"
)
type Limiter interface {
	Wait()
}
type Logger struct {
	ctx    context.Context
	client client.AddLogClient
	roots  *x509.CertPool
	toPost chan *toPost
	errors chan<- *FixError
	active uint32
	queued        uint32  
	posted        uint32  
	reposted      uint32  
	chainReposted uint32  
	wg      sync.WaitGroup
	limiter Limiter
	postCertCache  *lockedMap
	postChainCache *lockedMap
}
func (l *Logger) IsPosted(cert *x509.Certificate) bool {
	return l.postCertCache.get(hash(cert))
}
func (l *Logger) QueueChain(chain []*x509.Certificate) {
	if chain == nil {
		return
	}
	atomic.AddUint32(&l.queued, 1)
	h := hash(chain[0])  
	if l.postCertCache.get(h) {
		atomic.AddUint32(&l.reposted, 1)
		return  
	}
	h = hashChain(chain)
	if l.postChainCache.get(h) {
		atomic.AddUint32(&l.chainReposted, 1)
		return
	}
	l.postChainCache.set(h, true)
	l.postToLog(&toPost{chain: chain})
}
func (l *Logger) Wait() {
	l.wg.Wait()
}
func (l *Logger) RootCerts() *x509.CertPool {
	if l.roots == nil {
		for i := 0; i < 10; i++ {
			roots, err := l.getRoots()
			if err == nil {
				l.roots = roots
				return l.roots
			}
			log.Println(err)
		}
		log.Fatalf("Can't get roots for log")
	}
	return l.roots
}
func (l *Logger) getRoots() (*x509.CertPool, error) {
	roots, err := l.client.GetAcceptedRoots(l.ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to get roots: %s", err)
	}
	ret := x509.NewCertPool()
	for _, root := range roots {
		r, err := x509.ParseCertificate(root.Data)
		if x509.IsFatal(err) {
			return nil, fmt.Errorf("can't parse certificate: %s %#v", err, root.Data)
		}
		ret.AddCert(r)
	}
	return ret, nil
}
type toPost struct {
	chain []*x509.Certificate
}