// AllKeysChan runs a query for keys from the blockstore. // this is very simplistic, in the future, take dsq.Query as a param? // // AllKeysChan respects context func (bs *blockstore) AllKeysChan(ctx context.Context) (<-chan *cid.Cid, error) { // KeysOnly, because that would be _a lot_ of data. q := dsq.Query{KeysOnly: true} // datastore/namespace does *NOT* fix up Query.Prefix q.Prefix = BlockPrefix.String() res, err := bs.datastore.Query(q) if err != nil { return nil, err } output := make(chan *cid.Cid, dsq.KeysOnlyBufSize) go func() { defer func() { res.Close() // ensure exit (signals early exit, too) close(output) }() for { e, ok := res.NextSync() if !ok { return } if e.Error != nil { log.Errorf("blockstore.AllKeysChan got err:", e.Error) return } // need to convert to key.Key using key.KeyFromDsKey. k, err := dshelp.DsKeyToCid(ds.RawKey(e.Key)) if err != nil { log.Warningf("error parsing key from DsKey: ", err) continue } select { case <-ctx.Done(): return case output <- k: } } }() return output, nil }
// AllKeysChan runs a query for keys from the blockstore. // this is very simplistic, in the future, take dsq.Query as a param? // // AllKeysChan respects context func (bs *blockstore) AllKeysChan(ctx context.Context) (<-chan *cid.Cid, error) { // KeysOnly, because that would be _a lot_ of data. q := dsq.Query{KeysOnly: true} // datastore/namespace does *NOT* fix up Query.Prefix q.Prefix = BlockPrefix.String() res, err := bs.datastore.Query(q) if err != nil { return nil, err } // this function is here to compartmentalize get := func() (*cid.Cid, bool) { select { case <-ctx.Done(): return nil, false case e, more := <-res.Next(): if !more { return nil, false } if e.Error != nil { log.Debug("blockstore.AllKeysChan got err:", e.Error) return nil, false } // need to convert to key.Key using key.KeyFromDsKey. c, err := dshelp.DsKeyStringToCid(e.Key) if err != nil { log.Warningf("error parsing key from DsKey: ", err) return nil, true } return c, true } } output := make(chan *cid.Cid, dsq.KeysOnlyBufSize) go func() { defer func() { res.Process().Close() // ensure exit (signals early exit, too) close(output) }() for { k, ok := get() if !ok { return } if k == nil { continue } select { case <-ctx.Done(): return case output <- k: } } }() return output, nil }