func newIsolateServer(host, namespace string, config *retry.Config) *isolateServer { i := &isolateServer{ config: config, url: strings.TrimRight(host, "/"), namespace: namespace, } tracer.NewPID(i, "isolatedclient:"+i.url) return i }
// New returns a thread-safe Archiver instance. func New(is isolatedclient.IsolateServer, out io.Writer) Archiver { // TODO(maruel): Cache hashes and server cache presence. a := &archiver{ canceler: common.NewCanceler(), progress: progress.New(headers, out), is: is, maxConcurrentHash: 5, maxConcurrentContains: 64, maxConcurrentUpload: 8, containsBatchingDelay: 100 * time.Millisecond, containsBatchSize: 50, stage1DedupeChan: make(chan *archiverItem), stage2HashChan: make(chan *archiverItem), stage3LookupChan: make(chan *archiverItem), stage4UploadChan: make(chan *archiverItem), } tracer.NewPID(a, "archiver") a.wg.Add(1) go func() { defer a.wg.Done() a.stage1DedupeLoop() }() // TODO(todd): Create on-disk cache in a new stage inserted between stages 1 // and 2. This should be a separate interface with its own implementation // that 'archiver' keeps a reference to as member. a.wg.Add(1) go func() { defer a.wg.Done() a.stage2HashLoop() }() a.wg.Add(1) go func() { defer a.wg.Done() a.stage3LookupLoop() }() a.wg.Add(1) go func() { defer a.wg.Done() a.stage4UploadLoop() }() // Push an nil item to enforce stage1DedupeLoop() woke up. Otherwise this // could lead to a race condition if Close() is called too quickly. a.stage1DedupeChan <- nil return a }